以与注释类似的方式链接 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_related
和 Prefetch
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 %}
...
我有以下型号:
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_related
和 Prefetch
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 %}
...