You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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'但未提供默认值,无法执行该操作(数据库需要值来填充已存在的行)。
请选择修复方案:

  1. 现在提供一次性默认值(将应用于该列值为null的所有现有行)
  2. 退出,由您自行在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:无通用默认用户(适合生产环境/严格业务规范)

如果业务要求历史数据的创建人/更新人必须按规则赋值,不能统一使用默认值,可分三步完成迁移:

  1. 先给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)
    
  2. 执行python manage.py makemigrations && python manage.py migrate完成字段新增,此时旧数据的两个字段值为null
  3. 按照业务规则给所有旧数据填充合法的created_by、updated_by值,填充完成后去掉模型字段的null=True, blank=True配置,再次执行makemigrations和migrate即可完成全部变更。

内容的提问来源于stack exchange,提问作者Empusas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 21:36:01