【问题标题】:Prefetch_related in Django views results in surplus database queriesDjango 视图中的 Prefetch_related 导致多余的数据库查询
【发布时间】:2018-01-30 20:32:20
【问题描述】:

我想弄清楚我在这段代码中做错了什么:

contacts = Contact.objects.user(request.user).prefetch_related(
                        Prefetch('contact_phone',
                                 queryset = ContactPhone.objects.order_by('value')))

    for contact in contacts:
        for contact_phone in contact.contact_phone.all():
            # do something

Django 多次访问数据库。有任何想法吗 ?难道我可以在Django模板中使用prefetch_related,并且在视图中它多次访问数据库???

对于 10 个联系人,我有 10 个数据库命中,每一个看起来像这样:

SELECT ... FROM `contact_phone` WHERE `contact_phone`.`contact_id` = ...
ORDER BY `contact_phone`.`id` ASC LIMIT 1

所以,对我来说似乎有两件不清楚的事情。首先,为什么 Django 会为每个联系人打数据库。其次,为什么将电话号码限制为 1 条记录?

相应的模型如下所示:

class ContactPhone(BaseMixin):
    contact = models.ForeignKey(Contact, models.CASCADE, related_name = 'contact_phone')

【问题讨论】:

  • 什么是# do somethinguser(request.user)? 是什么我不确定您是否显示了足够的代码来解释问题。

标签: django django-orm


【解决方案1】:

每个Contact 得到一个查询,因为在prefetch_related 中您按value 排序,而在迭代中您不按任何属性排序。如果执行的查询与预取的查询不匹配,则执行新的查询。

https://docs.djangoproject.com/en/2.0/ref/models/querysets/#prefetch-related的注释:

请记住,与 QuerySet 一样,任何后续的链式 暗示不同数据库查询的方法将先前忽略 缓存结果,并使用新的数据库查询检索数据。

为避免额外的数据库查询,请执行以下操作:

contacts = Contact.objects.user(request.user).prefetch_related(
                        Prefetch('contact_phone',
                                 queryset = ContactPhone.objects.order_by('value')))

    for contact in contacts:
        for contact_phone in contact.contact_phone.order_by('value'):
            # do something

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 2019-03-16
    • 2011-02-05
    • 2021-10-21
    • 1970-01-01
    相关资源
    最近更新 更多