从不同的外键创建prefetch_related的联合

时间:2017-07-20 10:30:33

标签: django optimization django-orm

我有三个模型,让我们举一个想象的例子:

public class CustomView extends DefaultView { 

  public CustomView(Viewer viewer, String identifier, GraphRenderer graphRenderer) { 
    super(viewer, identifier, graphRenderer); 
  } 

  @Override 
  public void paintComponent(Graphics g) {  
    StackTraceElement[] stackElements = Thread.currentThread().getStackTrace(); 
    for (int i = 0; i < stackElements.length; i++) { 
      if (stackElements[i].getClassName().equals(ToolWindowsPane.class.getName())) { 
        repaint(); 
        break; 
      } 
    } 
    super.paintComponent(g); 
  } 

}

我们有一些人(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 = ... )可以分享他们自己的个人照片。我们在实体之间也有一些关系(由Entity表示),它们也可以共享它们的照片。

对于单个实体,我可以直接或通过关联检索与实体关联的所有照片,这样做:

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]) 预取,通过entity attr预取;两个将是完美的)会让我满意,但更重要的是能够迭代一个查询列表,在每个实体上

我试图查看association的内部代码,但看起来预取与查找相关联,而且我不知道如何在这种情况下进行Q查询(应该是什么Prefetch中的右操作数?)

注意:这里的重点不是重构数据库结构(Q(entity__in=...)用于其他许多事情,因此无法将其缩减为M2M { {1}}例如。)但如果可能的话,优化这个特定的用例。

1 个答案:

答案 0 :(得分:0)

我目前正在和Prefetch一起玩。我认为它的形状非常好,功能也很强大。

我对您的问题的处理方式可能类似于:

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",
))

然后您可以使用for entity in entities: entity.photos_prefetched访问这些照片。

如果这不起作用,则问题可能出在您正在引用(Q(entity=obj))到实际实体。不知道这是否正确可行。我在回引用该对象时遇到麻烦,可能是Django中的错误。