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

Django扩展Question基础模型遇迁移问题求助

问题解决指南

一、question_ptr字段的解释与处理

当你用Django的多表继承(基类非抽象类)时,子类会自动生成[父类名]_ptr格式的外键字段,这里的question_ptr就是用来关联Question父类主键的,作用是在子类表和父类表之间建立一对一关联。

后续迁移要求提供默认值,通常是因为你在已有父类数据的情况下新增了子类,或是修改了继承结构。如果你的业务不需要单独使用Question模型(所有问题都是具体题型),最优选择是把Question设为抽象基类;如果必须保留独立的Question模型,可手动修改迁移文件,为question_ptr设置合理默认值(比如指向现有Question实例ID),或允许字段为空(需确保业务逻辑合理)。

二、抽象基类反向查询名冲突的解决

把Question设为抽象类后,所有子类都会继承questionnaire字段,但默认的related_name='questions'会被所有子类共用,导致Django无法区分Questionnaire对应的是哪个子类的关联数据,从而触发冲突。

解决方法是修改基类中questionnaire字段的related_name,用Django提供的%(class)s占位符自动生成子类专属的反向查询名:

class Question(models.Model):
    questionnaire = models.ForeignKey(
        to='Questionnaire', 
        on_delete=models.CASCADE, 
        related_name='%(class)s_questions'
    )
    question = models.TextField()
    description = models.TextField(null=True, blank=True)
    media = models.FileField(upload_to='medias', blank=True, null=True)
    is_required = models.BooleanField(default=False)

    # 声明为抽象基类
    class Meta:
        abstract = True

    def __str__(self):
        return f'{self.questionnaire.name} - {self.question}'

这样每个子类(比如OptionalQuestion、TextAnswerQuestion)的反向查询名会自动变成optionalquestion_questions、textanswerquestion_questions,彻底避免冲突。

三、推荐方案

优先采用抽象基类的实现方式,因为你的场景是不同题型共享基础字段,不需要独立的Question实例。按上述代码修改后,重新生成迁移文件即可解决所有问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:33:19