以与注释类似的方式链接 Django QuerySets

Linking Django QuerySets in a similar way to annotations

我有以下型号:

class Foo(models.Model)
    bar = models.ForeignKey(Bar, on_delete=models.PROTECT)

class Bar(models.Model)
    ...

class Baz(models.Model)
    bar = models.ForeignKey(Bar, on_delete=models.PROTECT)

我想知道是否可以对 link 一个 Baz 查询集做一个类似于注释的事情到一个预过滤的 Foo 查询集。类似于:

queryset = Foo.objects.some_filter()
  .annotate(bazs=QuerySet('bar__baz_set.another_filter()'))

注意 Baz 查询集也被过滤了,Bar 可能并不总是有 Baz

这是我希望在模板中实现的:

{% for foo in queryset %}
    ...
    {% for baz in foo.bazs %}
    ...

您要查找的是 prefetch_relatedPrefetch

from django.db.models import Prefetch
queryset = Foo.objects.prefetch_related(
    Prefetch(
        'bar__baz_set',
        queryset=Baz.objects.filter(another_filter),
        to_attr='filtered_baz',
    )
)

这就是您在模板中的使用方式:

{% for foo in queryset %}
    ...
    {% for baz in foo.bar.filtered_baz %}
    ...

这是一个更直接的替代解决方案,但查询数量增加,正如其他答案的评论中所指出的那样。

class Foo(models.Model):
    bar = models.ForeignKey(Bar, on_delete=models.PROTECT)
    ...
    @cached_property
    def bar_bazs(self):
        return self.bar.get_bazs_by_some_filter()

class Bar(models.Model):
    ...
    def get_bazs_by_some_filter(self):
        return self.baz_set.some_filter()

并且在模板中:

{% for foo in queryset %}
    ...
    {% for baz in foo.bar_bazs %}
        ...