python - 在 Django 中使用 prefetch_related 连接 ManyToMany 字段

标签 python django orm

我可能遗漏了一些明显的东西,但我无法加入 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))

角色名称正确,但区域名称不正确。我在这里做错了什么?

最佳答案

无法访问角色 rr.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/

相关文章:

python - Django 对于从 View 中识别移动请求您有什么建议?

php - 学说 2 : Error: Class "..\.." has no field or association named "..."

python - 为 SQLAlchemy 多对多数据库设置关系/映射

python - 订阅后 Stripe 收费,从订阅中获取元数据

python - 模块未找到错误 : No module named 'models'

Python Pandas 基于 case 语句进行分组

javascript - Sequelize update with association 不更新关联模型的表

python - 渐变是 None 是 Pytorch

Python 包路径::查找应该是 .py 文件的目录

django - sorl thumbnail + django 生产中的问题