如果存在则从相关表中选择一条记录,否则返回None

时间:2017-11-10 11:54:37

标签: django

我有两个模型:

  class Box(models.Model):

  class BoxImages(models.Model):
     box=models.ForeignKey(Box)
     img=models.ImageField()
     cover=models.IntegerField(default=0)

只有一个图像可以是一个框的封面图像,一个框可能根本没有任何图像。我现在想要的是获取方框列表及其封面图片。但是django使用内连接并带来只有相应封面图像的盒子。

    Box.objects.filter(box_boximages__cover=1).values('id','box_label')

我如何强制它使用左连接或左外连接,因为我读了ORM自己决定使用哪个连接?

1 个答案:

答案 0 :(得分:1)

如果您想拥有所有方框,无论是否有封面图片,只需放下filter即可。过滤器有效地将您的查询集减少到仅具有封面图像的Box。

Box.objects.select_related('box_boximages').values('id','box_label', 'box_boximages__cover')

select_related将在同一查询中获取相关的BoxImages(如果存在)。查询集将包含所有Box对象,即使它们没有BoxImages。

编辑:

  

它返回所有图像;该框显示5项,因为它有5张图片。

是的,你是对的。 values将为每个fkey关系添加条目。有几种方法可以解决这个问题。

(a)最简单的是,不使用values,而是简单地遍历查询集并使用Box实例及其相关的BoxImages。代码很容易理解。使用select_related,你也应该表现得很好。

(b)使用聚合来仅获取封面的盒子图像。看看aggregate函数。您可以将其与Exists结合使用,以查找封面图片(或Max)。

(c)创建两个QuerySet,一个使用Boxes而不使用BoxImages,另一个使用BoxImage Covers获取所有相关的Box实例。结合这两个。

就我个人而言,我认为(a)是最简单的,因此最好在以后阅读代码或其他开发人员时理解。

如果您最终选择基于封面而不是封面图像,您可以自由更改模型,那么您可以考虑使用两个模型+模型继承并创建BoxCover( OneToOneRelation to Box)和BoxImage(n:1 to Box)模型。这将是最容易理解和处理的。