我正在尝试对具有特定字段值的所有相关模型进行计数。
这是一些代码...
models.py:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
BAD = "BAD"
MEH = "MEH"
GOOD = "GOOD"
GREAT = "GREAT"
REVIEW_CHOICES = (
(BAD, BAD.title()),
(MEH, MEH.title()),
(GOOD, GOOD.title()),
(GREAT, GREAT.title()),
)
title = models.CharField(max_length=100)
review = models.CharField(max_length=100, choices=REVIEW_CHOICES)
author = models.ForeignKey(Author, related_name="books")
假设我要列出每个作者的每种评论的数量。
我尝试过:
Authors.object.annotate(n_good_books=Count("books")).filter(books__review="GOOD").values("name", "n_good_books")
我也尝试过:
Authors.object.annotate(n_good_books=Count("books", filter=Q(books_review="GOOD"))).values("name", "n_good_books")
但是这些都不起作用。
有什么建议吗?
答案 0 :(得分:1)
您需要在.filter(..)
之前.annotate(..)
,
Authors.object.filter(
books__review="GOOD" # before the annotate
).annotate(
n_good_books=Count("books")
)
这将导致QuerySet
个Author
中的Author
,其中每个.n_good_books
都有一个额外的属性Book
,其中包含有效Author
的数量。相反的意思是,您<仅> 将检索{<1>至少个相关Book
经过了良好审查的annotate()
。就像specified in the documentation:
与
>>> from django.db.models import Count, Avg >>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors'))
子句一起使用时,过滤器具有以下作用: 约束要为其计算注释的对象。例如,您可以生成所有带有注释的书的带注释的列表 使用查询以“ Django”开头的标题:filter()
(..)
注释值也可以过滤。注释的别名可在以下位置的
exclude()
和>>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)
子句中使用 与其他模型字段相同。例如,生成具有多个书籍的书籍列表 作者,您可以发出以下查询:
Count(..., filter=Q(..))
此查询生成带注释的结果集,然后生成一个 根据该注释进行过滤。
public class CountryData : INotifyPropertyChanged
{
private string countryName;
public string CountryName
{
get { return countryName; }
set
{
countryName = value;
RaisePropertyChanged("CountryName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
方法仅自django-2.0起起作用,因此在django-1.11中这将无效。
答案 1 :(得分:0)
@ willem-van-onsem对我提出的问题有正确的答案。
但是,如果我想一次获得所有书籍类型的计数,我可以做类似的事情:
from django.db.models import Case, When, IntegerField
Authors.object.annotate(
n_bad_books=Count(Case(When(books__review="BAD", then=1), output_field=IntegerField())),
n_meh_books=Count(Case(When(books__review="MEH", then=1), output_field=IntegerField())),
n_good_books=Count(Case(When(books__review="GOOD", then=1), output_field=IntegerField())),
n_great_books=Count(Case(When(books__review="GREAT", then=1), output_field=IntegerField())),
)
他是对的,这非常优雅。