Django模型新增父类执行迁移时能否自动设置自定义默认值?
实现方法
你可以通过Submittable父类自带的__init_subclass__钩子,自动为所有继承它的子类预设父链接字段的默认值,完全不需要使用者手动修改迁移文件。
步骤1:编写实例创建工具函数
首先在app1/utils.py中定义创建Submittable实例的可调用对象:
# app1/utils.py from app1.models import Submittable def create_submittable(): new_submittable = Submittable.objects.create() return new_submittable.pk
步骤2:改造Submittable父类
在app1的模型定义中添加钩子逻辑,自动为子类注入带默认值的父链接字段:
# app1/models.py from django.db import models from app1.utils import create_submittable class Submittable(models.Model): is_submitted = models.BooleanField(default=False) def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) # 跳过抽象模型和父类自身,仅处理实际业务子类 if cls._meta.abstract or cls.__name__ == "Submittable": return ptr_field_name = f"{Submittable._meta.model_name}_ptr" # 避免重复添加字段 if ptr_field_name in [field.name for field in cls._meta.fields]: return # 显式定义带默认值的父链接字段 ptr_field = models.OneToOneField( Submittable, on_delete=models.CASCADE, parent_link=True, primary_key=True, default=create_submittable, editable=False, ) cls.add_to_class(ptr_field_name, ptr_field) # 其他类方法定义在此处
效果验证
使用者继承Submittable的时候不需要做任何额外配置,写法和之前完全一致:
# app2/models.py from app1.models import Submittable class Paper(Submittable): # 自有字段定义在此处 title = models.CharField(max_length=200)
执行makemigrations命令时不会再要求输入submittable_ptr_id的默认值,生成的迁移文件会自动带上你预设的create_submittable作为默认值。
注意事项
- 生成的迁移文件中
preserve_default=False是正常现象,Django不会将可调用对象固化到迁移代码中,后续修改create_submittable逻辑也不需要修改旧迁移文件 - 对于已经存在的旧模型新增继承
Submittable的场景,执行migrate时会自动为所有已存在的旧数据创建关联的Submittable实例
内容的提问来源于stack exchange,提问作者andreashhp
相关产品推荐
相关产品推荐

