我曾在django 2.X公司工作过,但我将在我的新项目中使用django3.x。在version2,我应该做外部连接。我使用prefetch_related并过滤了prefetch_related的模型。
在第2版中,如果我使用prefetch_related,就会将其作为单个查询进行查询。但是在第3版中,被多个查询所查询。
如果我只使用连接目标的Q()而不使用prefetch_related,那么它在版本3中可以执行单个查询。
from django.db import models
from django.db.models import Q
from django.db.models import Prefetch
class Member(models.Model):
member_no = models.AutoField()
member_name = models.CharField()
class Permission(models.Model):
permission_no = models.AutoField()
class MemberPermission(models.Model):
member_permission_no = models.AutoField()
member_no = models.ForeignKey(
Member, related_name='members', on_delete=models.CASCADE,
)
permission_no = models.ForeignKey(
Permission, related_name='member_permissions', on_delete=models.CASCADE,
)
my_permission = Member.objects.prefetch_related('member_permissions').filter(Q(member_permissions__isnull=False))[:1]
print(my_permission[0].member_permissions)
# member outer join permission, single query at django 2.X
# member outer join permission & additional query at django 3.x
my_permission = Member.objects.filter(Q(member_permissions__isnull=False))[:1]
print(my_permission[0].member_permissions)
# member outer join permission, single query at django 3.X
my_permission = Member.objects.prefetch_related(
Prefetch('member_permissions', MemberPermission.objects.select_related(
'permission_no').all())
).filter(Q(members__isnull=False))[:1]
print(my_permission[0].member_permissions.all()[0].permission_no.permission_no)
# member outer join permission & additional query at django 3.x如果我不使用prefetch_related,我可以得到一个查询。
但是,如果我想获得连接模型(成员对MemberPermission的许可),则不能。
我想知道如何通过Prefetch()在django3中查询一次。
发布于 2020-07-02 05:42:11
这不是版本上的区别。这是prefetch_related的工作方式。它将在每个外部联接中执行一个额外的查询。但是,这仍然比每次迭代执行一个查询少得多。文档在这一点上非常清楚:
select_related通过创建SQL并在SELECT语句中包含相关对象的字段来工作。因此,select_related在同一个数据库查询中获取相关对象。然而,为了避免因加入“多”关系而产生的大得多的结果集,select_related仅限于单值关系--外键和一对一关系。 另一方面,prefetch_related对每个关系进行单独的查找,并在Python中进行“连接”。这使得它可以预取多对多、多对一的对象,这些对象不能使用select_related完成,而且select_related还支持外键和一对一的关系。
因此,假设我们有两个外部联接,总共有1000个匹配行:
因此,担心每个联接增加一个查询是没有什么意义的。
https://stackoverflow.com/questions/62672962
复制相似问题