我有一个模型类Student
:
class Student(models.Model):
...
模型类Course
:
class Course(models.Model)
students = models.ManyToManyField(Student)
现在我想根据与课程相关的Students
的数量过滤Course
。我试过:
Course.objects.annotate(student_count = Count('students'))
但是由于某种原因,student_count
总是返回一个。
假设我创建了一门课程,并向其中添加了两名学生:
s1 = Student.objects.create()
s2 = Student.objects.create()
m1 = Course.objects.create()
m1.students.add(s1)
m1.students.add(s2)
print(Course.objects.all().first().students.count())
print(Course.objects.annotate(student_count = Count('students')).first().student_count
指纹
2
1
为什么这两种价值观不同?如何根据Students
的数量筛选课程?
3条答案
按热度按时间amrnrhlw1#
我测试了你的场景,结果是相同的两种方法:
结果正常:
也许你有订单吗?尝试删除
ordering
:8wigbo562#
您的问题来自注解零件。每次你添加注解部分到你的查询集,你也添加一个
group_by
到你的查询,如果你不添加特定的group_by
到你的查询集,它会自动为你添加它(即group_by "id"
)。然后你的结果变得更小,它会从你的查询结果中删除重复的内容(因为group_by
)。例如,看看这些查询集:虽然我尝试从两个查询集中获得第三个结果,但最终结果是不同的,因为这两个查询集的长度不同(
Course.objects.all()
和Course.objects.annotate(student_count=Count("students")
)。所以如果你看看这些与我们的查询集相关的查询:您可以在第二个查询中看到按部件分组。还要注意的是,你应该使用第二个来获得正确的结果(除了某些情况下,你知道你想要的结果在第一个查询集中的确切索引)。否则,总是会出现这样的情况,您可能会得到不同或错误的结果,因为您的第一个或最后一个记录可能会在注解中发生更改。
yzxexxkh3#
作为一个客人,我不能对此(或评论)投赞成票,但这是我(和其他人)遇到的一个真实的的问题。这里的答案都没有解释这个行为,但是下面有一个类似的bug:
Django query annotate after filter doesn't work correctly
注意这个问题不是上面的重复。在本例中,没有调用.filter(),因此直接在管理器上调用.annotate()。这看起来是正确的,所以我不清楚为什么Count()总是报告1。
也许Student模型中的某些东西(未显示)会导致问题,例如第一个答案中建议的默认顺序。