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

如何在Django中复用Personnel模型创建多个子模型?

问题解决:Django复用非托管模型创建子模型

错误原因

你使用了Django默认的多表继承,这种继承机制会自动为子模型生成[父模型名]_ptr_id字段,用于关联父模型对应的数据库表。但你指定了子模型和父模型使用同一个db_table,导致Django尝试在同一个表中查找不存在的personnel_ptr_id字段,从而报错。

正确方案

方案1:抽象基类拆分(适用于需要独立模型类的场景)

将原模型的公共字段提取到抽象基类中,各个子模型继承该基类并仅声明自身需要的字段,所有模型指向同一个数据库表。

  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  # 标记为抽象基类,不会生成数据库表
  1. 重构原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'
  1. 创建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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:28:18