Django _meta 多对多
我正在写一个命令行工具,这个工具可以帮助我查看不同数据表之间的关系,这样我就不需要每次都去查模型文件来了解它们是怎么关联的。我使用了_meta
来获取这些信息。
看看下面这些示例模型:
class Foo:
...
class Bar:
foo = models.ManyToManyField(Foo)
然后,当我使用_meta
来查找多对多关系字段时,会发生这样的事情:
In [33]: Bar._meta.many_to_many
Out [33]: [<django.db.models.fields.related.ManyToManyField: foos>]
In [34]: Foo._meta.many_to_many
Out [34]: []
有没有什么方法可以通过请求Foo
模型的多对多关系,返回[<django.db.models.fields.related.ManyToManyField: bars>]
这个结果呢?
2 个回答
1
你可以使用下面的方法来获取一个Django模型的所有相关关系(反向关系)。通过使用 related_objects
,它会返回一个可迭代的对象,里面包含了所有与这个模型相关的关系定义。这个可迭代对象表示了所有的关系类型,包括 一对一
、一对多
、多对一
和 多对多
。
from django.db.models.fields.reverse_related import ManyToManyRel
from apps import models as app_models
def get_relations(obj):
main_model = obj._meta.model
counter = 0
for x in main_model._meta.related_objects:
counter += 1
relation = ''
if x.one_to_one:
relation = 'one-to-one'
elif x.one_to_many:
relation = 'one-to-many'
elif x.many_to_one:
relation = 'many-to-one'
elif x.many_to_many:
relation = 'many-to-many'
model = x.related_model
print "{}) Relation: {} {} {}".format(
counter, str(main_model._meta), relation, str(model._meta)
)
if isinstance(x, ManyToManyRel):
field_name = x.field.m2m_reverse_field_name()
query_set = x.through.objects.filter(**{field_name: obj})
else:
field_name = x.field.name
query_set = model.objects.filter(**{field_name: obj})
print "Count: {}".format(query_set.count())
print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
obj = app_models.ModelName.objects.get(id=123)
get_relations(obj)
希望这对你有帮助!
2
是的,有这个功能。下面的代码会返回一个模型的 RelatedObject
列表,这个列表是多对多字段的反向关系。
related_objects = Foo._meta.get_all_related_many_to_many_objects()
你可以通过 related_object.field
来访问这个字段。需要注意的是,这个字段仍然是从 Bar
指向 Foo
的,它和通过 Bar._meta.many_to_many
返回的字段是完全一样的。
如果你想获取所有指向或来自某个模型的多对多字段,可以这样做:
many_to_many = (Foo._meta.many_to_many
+ [r.field for r in Foo._meta.get_all_related_many_to_many_objects()])