这是我的问题:
我在外部数据库上有两个表,它们看起来像这样:
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()
此查询后,我需要在每个单元格中使用一些specs对象的“ 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,然后…感到惊讶……在每次迭代中都进行了查询:(
因此,我有第一个返回所有单元格的查询-对于每个单元格,我都有一个新查询,该查询获取了所需的规格。第一个还可以,但是以下所有问题对我来说都是个问题,不应该在那里。
我的问题:
我做错了什么?
预先感谢您的帮助!
答案 0 :(得分:0)
与预取相关的用法仅在需要所有实例时使用,但是在需要过滤时不起作用。例如:
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]
代替先尝试其他方法