代码之家  ›  专栏  ›  技术社区  ›  Benjamin Wohlwend

Django和条件聚合

  •  4
  • Benjamin Wohlwend  · 技术社区  · 14 年前

    class Author(models.Model):
        name = models.CharField('name', max_length=100)
    
    class Article(models.Model)
        title = models.CharField('title', max_length=100)
        pubdate = models.DateTimeField('publication date')
        authors = models.ManyToManyField(Author)
    

    现在我要选择所有作者,并用他们各自的文章数对他们进行注释。这和Django的是小菜一碟 aggregates . 问题是,它应该只计算已经发表的文章。根据 ticket 11305 在Django票证追踪器中,这还不可能。我试着用 CountIf 注释中提到,但它没有引用datetime字符串,也没有生成所需的所有连接。

    那么,除了编写自定义SQL之外,最好的解决方案是什么呢?

    3 回复  |  直到 14 年前
        1
  •  4
  •   iulian    8 年前

    conditional expressions 可用于构建查询集。

    有关更多详细信息,请参阅文档,但您的问题的快速解决方案如下所示:

    today = datetime.date.today()
    authors = Author.objects.all().annotate(article_count=Sum(
        Case(When(articles__pubdate__lt=today, then=1),
             output_field=IntegerField())
    ))
    

        2
  •  5
  •   Timofey Trukhanov    11 年前

    你可以用 django-aggregate-if ticket 11305 . 或者你可以用 extra queryset的方法(假设您的应用程序名为“articles”):

    Author.objects.all().extra(
        select={'article_count': 'SELECT COUNT(*) FROM "articles_article" '
                                 'INNER JOIN "articles_article_authors" '
                                 'ON "articles_article"."id" = '
                                 '   "articles_article_authors"."article_id" '
                                 'WHERE "articles_article_authors"."author_id" = '
                                 '      "articles_author"."id" '
                                 'AND "articles_article"."pubdate" IS NOT NULL'})
    
        3
  •  1
  •   Benjamin Wohlwend    14 年前

    我通过使用所需的 GROUP BY 语句,并为所述视图提供了一个模型 managed = False OneToOneField Author 桌子。这不是最有效或最优雅的解决方案,但它可以正常工作。