在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,这样就能精准筛选出你要的字段。
方法二:通过_meta.related_objects反向查找
如果需要获取反向的带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
相关产品推荐
相关产品推荐

