Django新增含created_by、updated_by公共模型执行migrations报错如何处理
Django 新增公共抽象模型字段迁移报错解决方案
问题背景
我计划为所有数据库对象添加created_by和updated_by字段,因此创建了一个供绝大多数其他模型继承使用的抽象公共模型,目前已经梳理了大部分适配逻辑,但执行makemigrations生成迁移文件时触发错误。
模型代码
class CommonModel(models.Model): """Common fields that are shared among all models.""" created_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT, editable=False, related_name="+") updated_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT, editable=False, related_name="+") created_at = models.DateTimeField(auto_now_add=True, editable=False) updated_at = models.DateTimeField(auto_now=True, editable=False) class Meta: abstract = True class Tag(CommonModel): """Tag to be used for device type""" name = models.CharField(max_length=255) def __str__(self): return self.name
错误提示
您正尝试为devicetype添加不可为空的字段'created_by'但未提供默认值,无法执行该操作(数据库需要值来填充已存在的行)。
请选择修复方案:
- 现在提供一次性默认值(将应用于该列值为null的所有现有行)
- 退出,由您自行在models.py中添加默认值
我在网上检索到的唯一"解决方案"是先给字段设置default='',重新运行makemigrations,之后再手动编辑迁移文件删除default=''配置。我认为这不是规范的处理方式,请问是否有更合理的解决办法?
规范解决方案
报错核心原因是当前数据库中继承CommonModel的表已经存在历史数据,新增的created_by、updated_by是不可为空的外键字段,数据库需要为已有旧行填充合法值才能完成字段新增操作,可根据业务场景选择以下两种官方推荐的标准方案:
方案1:存在可复用的默认用户ID(适合开发环境/内部系统)
如果可以确定一个合法的用户ID作为历史数据的默认填充值(比如超级管理员ID、系统内置用户ID),直接在迁移交互环节选择选项1即可:
- 执行
python manage.py makemigrations触发交互时,输入1回车 - 输入对应默认用户ID(比如常用超级管理员ID为1就输入
1)回车完成操作
该操作只会在本次迁移中使用一次默认值,不会修改模型代码,完全符合Django迁移设计逻辑,无需后续手动调整迁移文件。
方案2:无通用默认用户(适合生产环境/严格业务规范)
如果业务要求历史数据的创建人/更新人必须按规则赋值,不能统一使用默认值,可分三步完成迁移:
- 先给
created_by、updated_by字段添加允许为空配置,保留editable=False不变:created_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT, editable=False, related_name="+", null=True, blank=True) updated_by = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT, editable=False, related_name="+", null=True, blank=True) - 执行
python manage.py makemigrations && python manage.py migrate完成字段新增,此时旧数据的两个字段值为null - 按照业务规则给所有旧数据填充合法的
created_by、updated_by值,填充完成后去掉模型字段的null=True, blank=True配置,再次执行makemigrations和migrate即可完成全部变更。
内容的提问来源于stack exchange,提问作者Empusas
相关产品推荐
相关产品推荐

