如何在 Django 中执行 LEFT OUTER JOIN QuerySet - 多对一

How to do a LEFT OUTER JOIN QuerySet in Django - Many to One

我有两个模型:Image(filename, uploaded_at) 和 Annotation (author, quality,... fk Image)。

一张图片可以有多个Annotations,一个Annotation属于一张图片。

我想构建一个查询集来获取满足某些条件的所有注释(包括与图像的关系,以便我也可以显示图像字段)。

到这里为止一切正常,但我还想显示没有创建注释(左外连接)的图像,但不确定我该如何继续执行此操作?

澄清一下,我正在尝试获取数据,这样我就可以像这样构建一个 table:

Image name, Image date, Annotation author, Annotation Quality
image 1   , 2019      , john             , high
image 2   , 2019      , doe              , high
image 3   , 2019      , null             , null
image 4   , 2014      , doe              , high

也许我使用了错误的方法,我使用 Annotation 作为主要模型,但是我似乎没有办法显示没有 Annotation 的图像,这有点有意义没有注释。 这就是我正在做的事情:

Annotation.objects.select_related('image').filter(Q(image__isnull=True)
 | Q(other condition))

但是,如果我使用图像作为主要模型,关系是对一张图像的许多注释,所以我不能使用 select_related,而且我不确定 prefetch_related 是否适合我需要。我不知道如何正确获取数据。我试过这个:

Image.objects.prefetch_related('annotations').filter(Q(annotations__isnull=True) | Q(other condition))

prefetch_related 似乎对查询没有任何影响,另外我想在 flat/the 同一行中添加注释数据(即第 1 行:图像 1,注释 1;第 2 行:图像 1、注释 2 等)而不必执行图像。annotation_set... 因为那不符合我的需要。

如果您需要外连接,它必须是左连接,正如您正确假设的那样。所以你必须从 Image 模型开始。要获得平面表示而不是嵌套 Annotation 对象,请使用 values(),其中 returns 字典查询集(而不是模型对象):

queryset_of_dictionaries = (Image.objects
    .filter(Q(annotations__isnull=True) | Q(other condition))
    .values('name', 'date', 'annotations__author', 'annotations__quality',
            # etc. – you have to enumerate all fields you need
    )
    # you'll probably want the rows in a particular order
    .order_by(
        # a field list like in values()
    )
)

# accessing the rows
for dic in queryset_of_dictionaries:
    print(f'Image name: {dic["name"]}, quality: {dic["annotations__quality"]}')