首页 > 解决方案 > Python prefetch_related 不缓存数据

问题描述

这是我的问题:

我在一个外部数据库上有两个表,如下所示:

class cell(models.Model):
    reference = models.CharField(max_length=36)   

class specs(models.Model):
    value_str = models.CharField(max_length=255, blank=True, null=True)
    name = models.CharField(max_length=255)
    linked = models.ForeignKey(cell, models.DO_NOTHING)

所以细胞有多个规格指向他。
我正在运行查询以获取一些具有其规格的单元格:

cells = cell.objects.using('db_name').prefetch_related('specs_set').all()

在这个查询之后,我为每个需要使用一些规格对象的单元格都有一个“for”:

for cell in cells :
    print(cell.reference)
    spec = cell.specs_set.filter(name='spec_name').first()
    print(spec.value_str)

这行得通,但是根据我对 prefetch_related 的理解,由于第一个查询,specs 对象应该被缓存,因此我不必在每次迭代时运行另一个查询来获取我的“spec_name”。

可以肯定的是,我在我的笔记本电脑上运行了一个 Wireshark 并且......令人惊讶......每次迭代都会进行一个查询 :(
所以我有第一个返回所有单元格的查询 - 对于每个单元格我都有一个新查询得到想要的规格。第一个是好的,但以下所有对我来说都是一个问题,他们不应该在那里。

我的问题:
我做错了什么?

在此先感谢您的帮助 !

标签: pythonsqldjangocaching

解决方案


仅当您需要所有实例时才使用与预取相关的用途,但如果您需要过滤它,这将不起作用。例如:

for cell in cells :
    print(cell.reference)
    spec = cell.specs_set.all()
    print(spec.value_str)

这将起作用

但如果你需要:

for cell in cells :
    print(cell.reference)
    spec = cell.specs_set.filter(name='spec_name').first()
    print(spec.value_str)

这行不通。

请参阅文档https://docs.djangoproject.com/en/2.1/ref/models/querysets/#prefetch-related

对于过滤,您应该像这样使用 Prefetch:

from django.db.models import Prefetch

qs = cpecs.objects.filter(name='spec_name')

cells = cell.objects.using(
    'db_name'
).prefetch_related(
    Prefetch('specs_set', queryset=qs)
).all()

请参阅文档https://docs.djangoproject.com/en/2.1/ref/models/querysets/#prefetch-objects

我不知道先,我认为这不适用于先,但您可以使用:

list(cell.specs_set.filter(name='spec_name'))[0]

而不是首先或尝试其他东西


推荐阅读