[英]Joining ManyToMany fields with prefetch_related in Django
I may be missing something obvious, but I'm having trouble getting a join on a ManyToMany field to work in a Django app. 我可能会遗漏一些明显的东西,但是我无法在ManyToMany字段上加入Django应用程序。 I have two models:
我有两个型号:
class Area(models.Model):
name = CharField(...)
class Role(models.Model):
name = CharField(...)
areas = ManyToManyField('Area', ...)
My goal is to have the equivalent of this query: 我的目标是拥有相当于这个查询:
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
The resulting data set would look like: 结果数据集如下所示:
Area Role
---------------------
A My Role
A Your Role
A Yo Mamas Role
B My Role
B Some Other Role
As you can see in the example, the My Role item appears twice, once for each area. 正如您在示例中所看到的,“ 我的角色”项目出现两次,每个区域出现一次。 I know I could get the list of areas and then get a list of roles for each (resulting in N+1 queries), but I'd like to be efficient about it if possible.
我知道我可以得到区域列表,然后获得每个区域的角色列表(产生N + 1个查询),但是如果可能的话我想要有效率。 As such, I found that prefetch_related might be what I wanted to use.
因此,我发现prefetch_related可能是我想要使用的。 When I use this, however, I end up with all Area values as None .
但是,当我使用它时,我最终将所有Area值都设置为None 。 Here's what I tried:
这是我试过的:
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))
The role names come along for the ride correctly, but the area names do not. 角色名称正确用于骑行,但区域名称没有。 What am I doing wrong here?
我在这做错了什么?
It isn't possible to access r.areas__name
for a Role r
. 无法访问角色
r
r.areas__name
。 You still have to access the roles via r.areas.all()
. 您仍然必须通过
r.areas.all()
访问角色。 However, by using prefetch_related
, you fetch all the related objects in one extra query, instead of O(n) queries. 但是,通过使用
prefetch_related
,您可以在一个额外查询中获取所有相关对象,而不是O(n)查询。
Since you want to order by area name, you should probably use the Area
model for your queryset, then loop through the related roles. 由于您希望按区域名称排序,因此您应该使用
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
That should give you the ordering you want, as long as the Role
model is ordered by name
by default. 这应该为您提供所需的顺序,只要默认情况下按
name
排序Role
模型。 If not, you could use a Prefetch
object to order the related queryset. 如果没有,您可以使用
Prefetch
对象来订购相关的查询集。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.