我可能遗漏了一些明显的东西,但我无法加入 ManyToMany 字段以在 Django 应用程序中工作。我有两个模型:
class Area(models.Model):
name = CharField(...)
class Role(models.Model):
name = CharField(...)
areas = ManyToManyField('Area', ...)
我的目标是得到这个查询的等价物:
select a.name, r.name
from area a
join area_role ar on ar.area_id = a.id
join role r on ar.role_id = r.id
order by a.name, r.name
生成的数据集如下所示:
Area Role
---------------------
A My Role
A Your Role
A Yo Mamas Role
B My Role
B Some Other Role
如您在示例中所见,我的角色 项出现了两次,每个区域一次。我知道我可以获取区域列表,然后获取每个区域的角色列表(导致 N+1 查询),但如果可能的话,我想提高效率。因此,我发现 prefetch_related可能是我想用的。然而,当我使用它时,我最终得到的所有区域值都是无。这是我尝试过的:
rqs = ( Role.objects.filter(areas__id__in=[1,2,3])
.prefetch_related(areas).order_by('areas__name', 'name') )
for r in rqs:
print("Area Name: " + str(r.areas.name))
print("Role Name: " + str(r.name))
角色名称正确,但区域名称不正确。我在这里做错了什么?
最佳答案
无法访问角色 r
的 r.areas__name
。您仍然必须通过 r.areas.all()
访问角色。但是,通过使用 prefetch_related
,您可以在一个额外的查询中获取所有相关对象,而不是 O(n) 查询。
因为你想按区域名称排序,你应该为你的查询集使用 Area
模型,然后循环遍历相关角色。
areas = Area.objects.filter(id__in=[1, 2, 3]).order_by('name').prefetch_related('role_set')
for area in areas:
roles = area.role_set.all()
for role in roles:
print area.name, roles.name
只要 Role
模型默认按 name
排序,那应该会给您想要的排序。如果没有,您可以使用 Prefetch
对象对相关查询集进行排序。
关于python - 在 Django 中使用 prefetch_related 连接 ManyToMany 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33112924/