【问题标题】:Python prefetch_related doesn't cache dataPython prefetch_related 不缓存数据
【发布时间】:2018-08-08 17:01:08
【问题描述】:

这是我的问题:

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

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 并且......令人惊讶......每次迭代都会进行查询:(
所以我有第一个返回所有单元格的查询 - 对于每个单元格,我都有一个新查询来获取所需的规格。第一个没问题,但以下所有对我来说都是一个问题,它们不应该在那里。

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

提前感谢您的帮助!

【问题讨论】:

    标签: python sql django caching


    【解决方案1】:

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

    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

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

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

    而不是首先或尝试其他方法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-11
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-23
      • 1970-01-01
      相关资源
      最近更新 更多