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

为何model._meta.get_fields()返回意外关联列名?如何规避?

问题:Django模型_meta.get_fields()返回反向关联字段,如何只获取实际数据库字段?

模型代码

class User(AbstractUser):
    pass

class Medium(models.Model):
    researcher = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True, related_name="medium_researcher")
    old_medium_name = models.CharField(max_length=20, null=True, blank=True)

class Uptake(models.Model):
    material_quality = models.CharField(max_length=20, null=True, blank=True)
    medium = models.ForeignKey(Medium, on_delete=models.CASCADE, blank=True, null=True, related_name="uptake_medium")

字段获取代码及问题

from database.models import Medium
MODEL_HEADERS=[f.name for f in Medium._meta.get_fields()]
MODEL_HEADERS
# 输出:['uptake_medium', 'id', 'researcher', 'old_medium_name']

疑问:uptake_medium是Uptake模型中定义的ForeignKey关联字段,仅属于Uptake模型,后台管理和SQLite数据库中都看不到该列,为什么_meta.get_fields()会返回它?如何只获取Medium模型的实际数据库字段?


解答

原因说明

_meta.get_fields()默认会返回模型的所有关联字段,包括正向关联和反向关联。uptake_medium是Uptake模型中medium字段指定的related_name,Django ORM会自动为Medium模型创建这个反向关联的虚拟字段,用于从Medium实例快速关联到对应的Uptake实例。这个字段仅存在于ORM层面,不会在数据库中生成实际列,因此后台管理和数据库里都看不到它。

解决方案

要只获取模型对应数据库中实际存在的字段,有两种简单的过滤方式:

方式一:过滤concrete属性为True的字段

concrete属性为True的字段,就是数据库中会生成实际列的字段,反向关联字段的该属性为False,直接过滤即可:

from database.models import Medium
MODEL_HEADERS = [f.name for f in Medium._meta.get_fields() if f.concrete]
# 输出:['id', 'researcher', 'old_medium_name']

方式二:结合get_fields()参数+属性过滤

如果需要排除父类继承的字段(比如从models.Model继承的id),可以添加include_parents=False参数再过滤:

from database.models import Medium
MODEL_HEADERS = [
    f.name for f in Medium._meta.get_fields(include_parents=False, include_hidden=False)
    if f.concrete
]
# 输出:['researcher', 'old_medium_name']

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:50:26