如何使用单个查询集获取关系模型中的所有相关对象?
How to get all related objects in relationship model with single queryset?
我想从具有单个查询集的用户模型中获取所有对象,但我不知道该怎么做。
我得到了一个 2 到用户模型的关系模型,
我可以用下面的这些代码得到对象
User.objects.get(id=1).profile
User.objects.get(id=1).groups
但是我怎样才能只用一个查询集获取用户的所有对象呢?
使用 select_related
和 prefetch_related
,如所述 here:
user = User.objects.select_related('profile').prefetch_related('groups').get(id=1)
user.profile # does not query the database again
user.groups # does not query the database again
但是请注意,由于 user
<-> groups
是 m2m 关系,无论如何这都会访问数据库两次。如果您只获取一个特定用户,添加 prefetch_related
并没有真正的区别。如果你遍历用户列表,它确实会有所不同,因为只需要一个查询来获取所有 m2m 相关组,而不是每个用户一个查询:
users = User.objects.select_related('profile').prefetch_related('groups')\
.filter(is_staff=True)
for user in users: # 2 queries
print(user.profile)
for group in user.groups: # no database query
print(group.name)
您可以通过以下格式的双下划线访问queryset中的ManyToMany,Foreign字段数据。
columnname.referred.table__reference_column
class DigitalApplicationsAndPlatform(models.Model):
digital_area = models.ForeignKey(MasterDigitalProductsAreas, on_delete=models.CASCADE)
keywords = models.ManyToManyField("MasterKeyword", blank=True, related_name="digital_keyword")
查询集:
m = models.DigitalApplicationsAndPlatform.objects.filter(id=1).values('digital_product', 'digital_area__digital_area', 'keywords__keyword')
上面的查询集将有多个值 digital_product,digital_area__digital_area,因为关键字字段具有 ManyToMany 关系。
结果:
<QuerySet [{'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': '_10000ft Insights_'}, {'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': '_10K Insights_'}, {'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': '_10,000ft Insights_'}, {'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': "_10K' Insights_"}]>
以上查询对性能有影响。每次您尝试访问相关模型数据时,Django 都会访问数据库。
m = models.DigitalApplicationsAndPlatform.objects.filter(id=1).select_related('digital_area').prefetch_related('keywords').values('digital_product', 'digital_area__digital_area', 'keywords__keyword')
你已经使用下面的提示来解决上面的查询集。
- select_related - 对于外键和 OneToOne 字段。
- prefetch_related - 对于多对多和反向查找
下面官方文档会给出一些访问相关数据的思路。
https://docs.djangoproject.com/en/2.2/topics/db/queries/#lookups-that-span-relationships
我想从具有单个查询集的用户模型中获取所有对象,但我不知道该怎么做。
我得到了一个 2 到用户模型的关系模型, 我可以用下面的这些代码得到对象
User.objects.get(id=1).profile
User.objects.get(id=1).groups
但是我怎样才能只用一个查询集获取用户的所有对象呢?
使用 select_related
和 prefetch_related
,如所述 here:
user = User.objects.select_related('profile').prefetch_related('groups').get(id=1)
user.profile # does not query the database again
user.groups # does not query the database again
但是请注意,由于 user
<-> groups
是 m2m 关系,无论如何这都会访问数据库两次。如果您只获取一个特定用户,添加 prefetch_related
并没有真正的区别。如果你遍历用户列表,它确实会有所不同,因为只需要一个查询来获取所有 m2m 相关组,而不是每个用户一个查询:
users = User.objects.select_related('profile').prefetch_related('groups')\
.filter(is_staff=True)
for user in users: # 2 queries
print(user.profile)
for group in user.groups: # no database query
print(group.name)
您可以通过以下格式的双下划线访问queryset中的ManyToMany,Foreign字段数据。
columnname.referred.table__reference_column
class DigitalApplicationsAndPlatform(models.Model):
digital_area = models.ForeignKey(MasterDigitalProductsAreas, on_delete=models.CASCADE)
keywords = models.ManyToManyField("MasterKeyword", blank=True, related_name="digital_keyword")
查询集:
m = models.DigitalApplicationsAndPlatform.objects.filter(id=1).values('digital_product', 'digital_area__digital_area', 'keywords__keyword')
上面的查询集将有多个值 digital_product,digital_area__digital_area,因为关键字字段具有 ManyToMany 关系。
结果:
<QuerySet [{'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': '_10000ft Insights_'}, {'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': '_10K Insights_'}, {'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': '_10,000ft Insights_'}, {'digital_product': '10,000ft Insights', 'digital_area__digital_area': 'Productivity & Collaboration', 'keywords__keyword': "_10K' Insights_"}]>
以上查询对性能有影响。每次您尝试访问相关模型数据时,Django 都会访问数据库。
m = models.DigitalApplicationsAndPlatform.objects.filter(id=1).select_related('digital_area').prefetch_related('keywords').values('digital_product', 'digital_area__digital_area', 'keywords__keyword')
你已经使用下面的提示来解决上面的查询集。
- select_related - 对于外键和 OneToOne 字段。
- prefetch_related - 对于多对多和反向查找
下面官方文档会给出一些访问相关数据的思路。
https://docs.djangoproject.com/en/2.2/topics/db/queries/#lookups-that-span-relationships