如何在Django中复用Personnel模型创建多个子模型?
问题解决:Django复用非托管模型创建子模型
错误原因
你使用了Django默认的多表继承,这种继承机制会自动为子模型生成[父模型名]_ptr_id字段,用于关联父模型对应的数据库表。但你指定了子模型和父模型使用同一个db_table,导致Django尝试在同一个表中查找不存在的personnel_ptr_id字段,从而报错。
正确方案
方案1:抽象基类拆分(适用于需要独立模型类的场景)
将原模型的公共字段提取到抽象基类中,各个子模型继承该基类并仅声明自身需要的字段,所有模型指向同一个数据库表。
- 定义抽象基类
class BasePersonnel(models.Model): id = models.AutoField(primary_key=True) card_number = models.BigIntegerField() name = models.TextField(db_collation='C') family = models.TextField(db_collation='C') def __str__(self) -> str: return f'{self.card_number} - {self.family} - {self.name}' class Meta: abstract = True # 标记为抽象基类,不会生成数据库表
- 重构原Personnel模型
class Personnel(BasePersonnel): height = models.TextField(db_collation='C', blank=True, null=True) weight = models.FloatField(blank=True, null=True) job_type = models.BigIntegerField(db_column='Job_Type', blank=True, null=True) age = models.FloatField(db_column='age', blank=True, null=True) Superviser_score = models.FloatField(db_column='Superviser_score', blank=True, null=True) QC_score = models.FloatField(db_column='QC_score', blank=True, null=True) class Meta: managed = False db_table = 'personnel'
- 创建SuperviserModel子模型
class SuperviserModel(BasePersonnel): # 仅声明该模型需要的字段,需与数据库表字段对应 center = models.TextField(blank=True, null=True) # 根据实际表字段类型调整 distance = models.FloatField(blank=True, null=True) job_type = models.BigIntegerField(db_column='Job_Type', blank=True, null=True) overtime = models.FloatField(blank=True, null=True) class Meta: managed = False db_table = 'personnel'
同理可以创建QcModel、BioModel等,只需继承BasePersonnel并声明对应字段即可。
方案2:多Admin类注册(适用于仅在后台展示不同字段的场景)
如果不需要独立的模型类,只是想在Django Admin中展示不同的字段子集,可以为同一个Personnel模型注册多个Admin类,每个类控制不同的显示/编辑字段。
@admin.register(Personnel) class MyPersonelAdmin(admin.ModelAdmin): list_display = ['card_number','name','family','center','job_type'] @admin.register(Personnel) class SuperviserAdmin(admin.ModelAdmin): verbose_name = "主管人员" verbose_name_plural = "主管人员" list_display = ['card_number','name','family','center','distance','job_type','overtime'] # 控制编辑页面显示的字段 fields = ['card_number','name','family','center','distance','job_type','overtime'] @admin.register(Personnel) class QcAdmin(admin.ModelAdmin): verbose_name = "质检人员" verbose_name_plural = "质检人员" list_display = ['card_number','name','family','QC_score'] fields = ['card_number','name','family','QC_score']
这种方式无需创建新模型,仅通过Admin配置实现不同的字段展示逻辑。
内容的提问来源于stack exchange,提问作者henrry
相关产品推荐
相关产品推荐

