代码之家  ›  专栏  ›  技术社区  ›  Daniel Holmes

以类似于注释的方式链接Django查询集

  •  0
  • Daniel Holmes  · 技术社区  · 6 年前

    我有以下型号:

    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)
    

    我想知道是否可以做一些类似于注释的事情来链接 Baz Foo queryset。比如:

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

    巴兹 queryset也会被过滤,并且 Bar 巴兹

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

    {% for foo in queryset %}
        ...
        {% for baz in foo.bazs %}
        ...
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   schillingt    6 年前

    你要找的是 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 %}
        ...
    
        2
  •  0
  •   Daniel H.    6 年前

    这里有一个更简单的替代解决方案,但正如另一个答案的评论中所指出的,它增加了查询的数量。

    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 %}
            ...