【问题标题】:Django query caching through a ForeignKey on a GenericRelation通过 GenericRelation 上的 ForeignKey 进行 Django 查询缓存
【发布时间】:2017-01-17 05:06:40
【问题描述】:

使用GenericRelationRecords 映射到Persons,我有以下代码,它可以正常工作,但我正在尝试解决一个性能问题:

models.py

class RecordX(Record):  # Child class
    ....

class Record(models.Model):  # Parent class
    people = GenericRelation(PersonRecordMapping)

    def people_all(self):
        # Use select_related here to minimize the # of queries later
        return self.people.select_related('person').all()

    class Meta:
        abstract = True

class PersonRecordMapping(models.Model):
    person = models.ForeignKey(Person)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

class Person(models.Model):
    ...

总的来说,我有:

RecordX ===GenericRelation===> PersonRecordMapping ===ForeignKey===> Person

我的应用程序中的显示逻辑遵循这些关系来显示映射到每个RecordX 的所有Person

views.py

@rendered_with('template.html')
def show_all_recordXs(request):
    recordXs = RecordX.objects.all()
    return { 'recordXs': recordXs }

问题出在模板中:

template.html

{% for recordX in recordXs %}
    {# Display RecordX's other fields here #}
    <ul>
    {% for map in record.people_all %}{# <=== This generates a query every time! #}
        <li>{{ map.person.name }}</li>
    {% endfor %}
    </ul>
{% endfor %}

如前所述,每次我请求与RecordX 相关的Persons 时,它都会生成一个新查询。我似乎无法弄清楚最初如何预取这些以避免冗余查询。

如果我尝试selected_related,我会收到一条错误消息,指出此处没有selected_related 字段(错误消息:Invalid field name(s) given in select_related: 'xxx'. Choices are: (none))。毫不奇怪,我现在明白了——这个模型上没有任何 FK。

如果我尝试prefetch_related('people'),不会引发错误,但我仍然会在模板中的每个循环上得到与以前相同的重复查询。 prefetch_related('people__person') 也是如此。如果我尝试prefetch_related('personrecordmapping'),我会得到一个错误。

按照this answer 的思路,我考虑过尝试通过以下方式模拟select_related

PersonRecordMapping.objects.filter(object_id__in=RecordX.objects.values_list('id', flat=True))

但我不太了解_content_object_cache,无法根据我的情况调整这个答案(即使是正确的方法)。

那么——我怎样才能将所有Persons 预取到RecordXs 以避免在页面显示时 n 查询 n @987654344 @对象?

感谢您的帮助!

【问题讨论】:

    标签: django django-queryset django-generic-relations


    【解决方案1】:

    Ack,显然我需要调用 both -- prefetch_related('people', 'people__person')。叹息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-09
      • 2011-05-09
      • 2021-05-26
      • 2014-05-07
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多