如何使用单个查询集获取关系模型中的所有相关对象?

问题描述 投票:0回答:2

我想从具有单个查询集的用户模型中获取所有对象,但我不知道如何做到这一点。

我得到了一个与用户模型的2关系模型, 我可以使用下面的代码获取对象

User.objects.get(id=1).profile
User.objects.get(id=1).groups

但是我如何才能仅使用单个查询集获取用户的所有对象?

django django-models django-queryset django-orm
2个回答
5
投票

使用

select_related
prefetch_related
,如此处所述:

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)

1
投票

您可以使用以下格式的双下划线访问查询集中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 的多个值,因为 keywords 字段具有多对多关系。

结果:

<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

© www.soinside.com 2019 - 2024. All rights reserved.