簡體   English   中英

在Django中使用prefetch_related連接ManyToMany字段

[英]Joining ManyToMany fields with prefetch_related in Django

我可能會遺漏一些明顯的東西,但是我無法在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可能是我想要使用的。 但是,當我使用它時,我最終將所有Area值都設置為None 這是我試過的:

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

這應該為您提供所需的順序,只要默認情況下按name排序Role模型。 如果沒有,您可以使用Prefetch對象來訂購相關的查詢集。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM