Django 将与不同外键相关的预取_合并
我有三个模型,让我们举一个虚构的例子:Django 将与不同外键相关的预取_合并,django,optimization,django-orm,Django,Optimization,Django Orm,我有三个模型,让我们举一个虚构的例子: class Entity(models.Model): name = models.CharField() class EntityAssociation(models.Model): buddy1 = models.ForeignKey(Entity, related_name='+') buddy2 = models.ForeignKey(Entity, related_name='+') class EntityPhoto
class Entity(models.Model):
name = models.CharField()
class EntityAssociation(models.Model):
buddy1 = models.ForeignKey(Entity, related_name='+')
buddy2 = models.ForeignKey(Entity, related_name='+')
class EntityPhoto(models.Model):
entity = models.ForeignKey(Entity, null=True)
association = models.ForeignKey(EntityAssociation, null=True)
title = ...
我们有一些人(实体
),他们可以分享自己的个人照片。我们还有一些实体之间的关系(由EntityAssociation
表示),它们也可以一起共享照片
对于单个实体,我可以直接或通过关联检索与实体关联的所有照片,这样做:
obj = Entity.objects.last()
EntityPhoto.objects.filter(
Q(entity=obj) | Q(association__buddy1=obj) | Q(association__buddy2=obj)
)
我想要的是能够预取所选实体集的所有照片。典型的用例是:
for entity in Entity.objects.all().prefetch(???):
print(entity.name, 'has', len(entity.photos_prefetched), 'photos')
print([x.title for x in entity.photos_prefetched])
这应该是返回所有的照片。一个包含三个查询的解决方案(实体列表、通过实体预取、通过关联预取、两个查询都是完美的)可以满足我的要求,但更重要的是能够在每个实体上迭代单个列表
我试图查看Prefetch
的内部代码,但它看起来像是预取与查找绑定在一起,而且我不知道在这种情况下如何进行Q查询(在Q(entity\uu in=…)
中什么应该是正确的操作数?)
注意:这里的重点不是重构数据库结构(EntityAssociation
用于很多其他事情,因此它不能被简化为EntityTo
的M2M),而是优化这个特定的用例,如果可能的话。我目前正在玩预取。在我看来,这是一个相当好的形状和相当强大
我解决您问题的方法可能是:
entities = Entity.objects.all().prefetch(Prefetch(
'entity_photo__set',
EntityPhoto.objects.filter(
Q(entity=obj) | Q(association__buddy1=obj) | Q(association__buddy2=obj
)
to_attr="photos_prefetched",
))
然后,您可以在entities:entity.photos\u prefetched
中为entity访问这些照片
如果这不起作用,问题可能是您正在引用回实际实体(Q(entity=obj)
)。不确定这是否正确可行。我在引用回对象时遇到问题,可能是Django中的一个bug。你有一个好的解决方案吗?@konoufo没有。我仍在进行两次单独的预取以获取实体的所有照片。然而,我的用例不断发展,因此我不再需要单一的合并列表,因此我没有进一步挖掘:-)