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

在Django 2.0.7中获取含through模型的M2M字段列表方法

获取Django 2.0.7中带through中间表的多对多字段

嘿,这个问题我之前在项目里也踩过坑!确实,Django里带自定义through中间表的多对多字段不会出现在local_many_to_many里——因为这种关系本质上是通过中间模型来维护的,Django会把它归类为一种特殊的关联关系,而不是普通的多对多字段。下面是我当时解决这个问题的方法:

1. 先明确两种多对多的区别

  • 普通多对多(无自定义through):Django自动生成中间表,这类字段会被归类到local_many_to_many中,你已经知道怎么获取了。
  • 带自定义through的多对多:你手动指定了中间模型,Django不会把它放进local_many_to_many,需要从模型的元数据里找特殊的关联项。

2. 获取带through的多对多字段

方法一:通过_meta.get_fields()筛选

get_fields()方法会返回模型所有的字段和关联关系,我们可以从中筛选出带自定义through的多对多字段:

# 假设你的模型是MyModel
from myapp.models import MyModel

model = MyModel
# 筛选带through的多对多字段
through_m2m_fields = [
    field for field in model._meta.get_fields(include_parents=False)
    if field.many_to_many and hasattr(field.remote_field, 'through') 
    and not field.remote_field.through._meta.auto_created
]

这里的not field.remote_field.through._meta.auto_created是关键——普通多对多的中间表是Django自动创建的,auto_created为True;而你自定义的through模型auto_created为False,这样就能精准筛选出你要的字段。

如果需要获取反向的带through的多对多关联(比如从User模型找关联到它的Group模型的多对多字段),可以用这个方法:

from django.db.models.fields.related import ManyToManyRel

through_m2m_rels = [
    rel for rel in model._meta.related_objects
    if isinstance(rel, ManyToManyRel) and not rel.through._meta.auto_created
]

每个rel对象包含了关联的详细信息,比如rel.name是反向关联的名称,rel.field可以拿到对应的多对多字段。

3. 整合所有字段

把普通字段、普通多对多字段和带through的多对多字段整合在一起:

# 普通字段
regular_fields = list(model._meta.fields)
# 普通多对多字段
normal_m2m_fields = list(model._meta.local_many_to_many)
# 带through的多对多字段
through_m2m_fields = [
    field for field in model._meta.get_fields(include_parents=False)
    if field.many_to_many and hasattr(field.remote_field, 'through') 
    and not field.remote_field.through._meta.auto_created
]

# 所有字段的集合
all_model_fields = regular_fields + normal_m2m_fields + through_m2m_fields

验证示例

假设你有以下模型:

from django.db import models

class Membership(models.Model):
    user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    group = models.ForeignKey('Group', on_delete=models.CASCADE)
    join_date = models.DateField()

class Group(models.Model):
    name = models.CharField(max_length=100)
    members = models.ManyToManyField('auth.User', through=Membership)

当你对Group模型执行上面的代码时,through_m2m_fields会包含members这个字段;对User模型执行时,会通过related_objects找到反向的group_set关联。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:35:55