Django中ForeignKey外键使用方法及现有模型代码正确性问询
Django ForeignKey 正确使用规则及代码问题排查
外键基础使用规范
- 外键
ForeignKey用于定义模型间的一对多关联,必须指定关联的目标模型、on_delete行为两个必填参数,字段命名建议贴合关联语义,不要和业务字段命名混淆。 - 常见
on_delete取值:CASCADE:关联对象删除时,当前数据也同步删除SET_NULL:关联对象删除时,当前外键字段设为NULL,需要搭配null=True参数使用PROTECT:关联对象删除时抛出异常,阻止删除操作
你提供的代码存在的问题
1. CustomerDetail 模型
dob是DateField日期类型,你设置的默认值为空字符串'',和字段类型不匹配,运行会触发类型错误。可选修正方案:允许为空的话设置null=True, blank=True;要求必填的话移除默认值,或者设置合法日期默认值(如timezone.now,需先导入django.utils.timezone)。
2. orderview 模型
- 模型命名不符合Django规范,建议改为大驼峰格式
OrderView - 字段逻辑完全错位:你把关联客户的外键命名成了代表总金额的
overalltotal,反而把customer设为了普通字符字段,完全违背外键的使用逻辑。正确做法是删除customer = models.CharField(max_length=100,default='')这行,将外键字段命名为customer指向CustomerDetail,总金额overalltotal改用DecimalField存储数值。 - 当前外键的
on_delete=SET_NULL已经搭配了null=True, blank=True,这个参数设置本身是合规的,只是字段名和关联逻辑错了。
3. orderdetails 模型
- 模型命名不符合规范,建议改为大驼峰
OrderDetail - 外键
orderid设置了on_delete=SET_NULL,但没有加null=True参数,运行会直接报错,必须补充null=True - 存储金额的
total字段用了CharField字符类型,后续做统计、计算都会非常麻烦,建议改为IntegerField或DecimalField数值类型 - 外键命名不需要带
id后缀,Django会自动在数据库中生成xxx_id的列名,直接命名为order可读性更高
修正后的参考代码
from django.db import models from django.utils import timezone class CustomerDetail(models.Model): name = models.CharField(max_length=100, default='') phone_no = models.CharField(max_length=10, unique=True, default='') # 修正dob字段的默认值问题,这里示例允许为空 dob = models.DateField(null=True, blank=True) def __str__(self): return self.name class OrderView(models.Model): reference = models.CharField(max_length=100, default='') # 关联客户的外键,替换原来错位的字段 customer = models.ForeignKey(CustomerDetail, on_delete=models.SET_NULL, null=True, blank=True) # 总金额改用数值类型存储 overalltotal = models.DecimalField(max_digits=10, decimal_places=2, default=0) def __str__(self): return self.reference class OrderDetail(models.Model): product = models.CharField(max_length=100, default='') quantity = models.IntegerField() unit_price = models.IntegerField() # 金额改用数值类型 total = models.IntegerField() # 修正外键参数,修改命名 order = models.ForeignKey(OrderView, on_delete=models.SET_NULL, null=True) def get_total(self): result = self.quantity * self.unit_price return result def save(self, *args, **kwargs): self.total = self.get_total() super(OrderDetail, self).save(*args, **kwargs)
内容的提问来源于stack exchange,提问作者vtr
相关产品推荐
相关产品推荐

