【问题标题】:Get count on several filtered subqueries in template获取模板中几个过滤子查询的计数
【发布时间】:2014-07-01 10:15:57
【问题描述】:

我最近询问了如何计算模板中的过滤子查询,并在这里得到了答案:Get count on filtered subqueries in template

现在我意识到我需要这个扩展如下(我认为这比我的第一个问题要多得多,因此在这里创建一个新问题):

  1. 显示与标签不匹配的文章,但计数为 0。
  2. 扩展以允许对不同的标签进行计数。

使用以下模型:

class Category(models.Model):
    ...

class SubCategory(models.Model):
    category = models.ForeignKey(Category)
    ....

class Tag(models.Model):
    ....

class Article(models.Model)
    sub_category = models.ForeignKey(SubCategory)
    tag = models.ForeignKey(Tag)

我得到了以下答案 (views.py),它将创建一个 num_articles 变量来保存 tag='xyz' 的文章数:

def my_view(request, other, arguments):
    ...
    subcategories = category.sub_category_set.filter(tag__tagname='xyz') \ 
                            .annotate(num_articles=Count('article__id'))

还有模板:

{% for subcategory in subcategories %}
    {{ subcategory.name }} -- {{ subcategory.num_articles }}
{% endfor %}



但现在,我希望能够做这样的事情,让 独立 计数几个不同的标签,这样 'xyz' 的计数不依赖于 'abc' 的计数,反之亦然:

def my_view(request, other, arguments):
    ...
    subcategories = category.sub_category_set. \
        filter(tag__tagname='xyz').annotate(num_articles_xyz=Count('article__id')) \
        filter(tag__tagname='abc').annotate(num_articles_abc=Count('article__id')) \
        filter(tag__tagname='def').annotate(num_articles_def=Count('article__id')) \
        ...

在模板中用作:

{% for subcategory in subcategories %}
    {{ subcategory.name }} -- {{ subcategory.num_articles_xyz }}<br />
    {{ subcategory.num_articles_abc }} -- {{ subcategory.num_articles_def }}
    ...
{% endfor %}

并且还希望显示所有子类别,即使任何计数都不匹配。但是,该计数的值为 0。

【问题讨论】:

    标签: python django django-models django-templates django-views


    【解决方案1】:

    使用 Django ORM 没有简单、有效的方法来做到这一点。通过注释的实现,ORM 中无法对同一查询中的不同过滤集进行注释。即使您再次注解、过滤和注解,所有注解也会在最后一次注解时的过滤集上。我什至不确定你想要的在原始 SQL 代码中是否可行,但我不是这方面的专家。

    您可以获取所有相关的标签和文章,并在 Django 中进行实际的注释。但是,您必须小心:即使使用prefetch_related,如果您过滤相关集或以任何实际克隆查询集的方式对其进行更改,您仍将为每个查询集执行数据库查询。

    以下是您可以执行此操作的方法。它还将处理在该特定子类别中没有文章的任何标签。

    subcategories = category.sub_category_set.prefetch_related('tags', 'articles')
    for subcategory in subcategories:
        subcategory.num_articles = dict()
        for tag in tags:
            num = len([a for a in subcategory.articles.all() if a.tag_id == tag.id])
            subcategory.num_articles[tag.tag_name] = num
    

    在你的模板中:

    {% for subcategory in subcategories %}
        {{ subcategory.name }} <br />
        {% for k,v in subcategory.num_articles.iteritems %}
            {{ k }} -- {{ v }}
        {% endfor %}
    {% endfor %}
    

    这将产生 3 个数据库查询,无论标签数量如何(4 个包括对 category 的查询),并将在 python 中完成其余的处理。但是,从数据库中获取大型数据集可能会很昂贵。如果您需要处理非常大的数据集并看到性能问题,您可能想看看为每个标签执行一些优化良好的查询与仅在 python 中进行数据处理的几个大型查询相比如何。

    【讨论】:

      猜你喜欢
      • 2014-06-30
      • 2021-07-17
      • 2015-11-17
      • 1970-01-01
      • 2020-10-04
      • 2021-11-16
      • 2015-01-29
      • 2012-08-22
      • 2018-09-02
      相关资源
      最近更新 更多