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没有。我仍在进行两次单独的预取以获取实体的所有照片。然而,我的用例不断发展,因此我不再需要单一的合并列表,因此我没有进一步挖掘:-)