关于 Django 模型设计的思想
一、核心设计原则
1. 单一职责原则
- 每个模型只处理单一数据实体
避免创建包含过多职责的 “上帝模型”# 反例:混合用户认证与个人资料 class User(models.Model): username = models.CharField(max_length=30) email = models.EmailField() address = models.TextField() # 应拆分到 Profile 模型 # 正例:职责分离 class User(models.Model): username = models.CharField(max_length=30) email = models.EmailField() class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) address = models.TextField()
2. 规范化与反规范化平衡
- 第三范式基础:消除冗余数据
适当反范式优化:高频查询字段可冗余存储
class Article(models.Model):
title = models.CharField(max_length=200)
author_name = models.CharField(max_length=100) # 已经通过外键关联作者,冗余作者名称避免 JOIN
author = models.ForeignKey(User, on_delete=models.CASCADE)
二、数据结构优化策略
1. 字段类型选择
数据类型 | 推荐字段类型 | 说明 |
---|---|---|
短文本(≤255) | CharField | 优于 TextField 节省存储 |
大文本 | TextField | 配合 null=True 减少空值 |
枚举值 | IntegerField +选择 | 比 CharField 更省空间 |
精确数值 | DecimalField | 金融金额必须使用 |
2. 关系型字段设计
class Product(models.Model):
categories = models.ManyToManyField( # 多对多关系
'Category',
through='ProductCategory', # 自定义中间表
related_name='products'
)
class ProductCategory(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
priority = models.IntegerField(default=0) # 扩展中间表字段
三、性能优化关键点
1. 索引策略
class Order(models.Model):
order_number = models.CharField(max_length=32, db_index=True) # 单字段索引
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
models.Index(fields=['user', '-created_at']) # 复合索引
]
2. 查询优化技巧
# 预加载关联数据
orders = Order.objects.select_related('user').prefetch_related('items')
# 批量操作
Product.objects.bulk_create([Product(...), Product(...)])
Product.objects.filter(category=1).update(price=F('price') * 0.9)
# 仅需 ID 时使用 values_list
product_ids = Product.objects.filter(
stock__gt=0
).values_list('id', flat=True)
四、数据完整性保障
1. 字段约束配置
class Account(models.Model):
balance = models.DecimalField(
max_digits=10,
decimal_places=2,
default=0,
validators=[MinValueValidator(0)] # 余额不可为负
)
email = models.EmailField(unique=True) # 唯一性约束
2. 事务控制
from django.db import transaction
def transfer_funds(sender, receiver, amount):
with transaction.atomic():
sender.balance -= amount
sender.save()
receiver.balance += amount
receiver.save()
五、可维护性实践
1. 模型组织结构
# core/models/base.py(抽象基类)
class TimeStampedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
# products/models.py
class Product(TimeStampedModel):
name = models.CharField(max_length=200)
2. 注释文档
class ClinicalTrial(models.Model):
"""
临床试验核心模型
Attributes:
phase (int): 试验阶段 (1-4)
- 1: 安全性评估
- 2: 有效性验证
- 3: 大规模测试
- 4: 上市后监测
"""
phase = models.IntegerField(choices=((1, "Phase I"), ...))
六、扩展性设计
1. 多态模型实现
具体可参考博文【Django 多态模型实现详解】
from model_utils.models import TimeStampedModel
class MedicalDevice(TimeStampedModel):
manufacturer = models.ForeignKey(Manufacturer)
device_type = models.CharField(max_length=50) # 类型鉴别字段
class XRayMachine(MedicalDevice):
class Meta:
proxy = True # 代理模型扩展方法
def exposure_check(self):
return self.logs.filter(exposure__gt=500).exists()
2. 动态字段存储
class Product(models.Model):
attributes = models.JSONField(default=dict) # 存储动态属性
# 使用示例
product.attributes['screen_size'] = '6.1英寸'
七、安全防护措施
1. 输入验证
class PatientRecord(models.Model):
ssn = models.CharField(
max_length=11,
validators=[RegexValidator(r'^\d{3}-\d{2}-\d{4}$')]
)
2. 权限控制
class LabReport(models.Model):
class Meta:
permissions = [
('can_view_sensitive', "Can view sensitive reports")
]
八、测试与验证
1. 模型测试案例
class ProductModelTest(TestCase):
def test_inventory_alert(self):
p = Product.objects.create(stock=5, min_stock=10)
self.assertTrue(p.needs_restock)
def test_price_history(self):
with self.assertNumQueries(1):
history = Product.price_history.all()
九、工具链推荐
- 开发辅助工具
django-extensions
:./manage.py shell_plus
增强django-model-utils
:提供TimeStampedModel
等基类django-debug-toolbar
:SQL
查询分析
- 质量监控
pylint-django
:模型代码静态检查factory_boy
:测试数据生成django-migration-linter
:检测破坏性迁移
通过以上九个维度的系统化设计,可以创建出高性能、易维护且安全的 Django 数据模型。关键要平衡规范化与性能需求,同时保持代码的可扩展性。建议定期通过 python manage.py check
进行模型健康检查,并持续优化数据库索引策略