django注释一个函数,该函数返回具有特征的所有对象中的字段的最大值

时间:2016-06-28 12:17:22

标签: python django django-orm django-annotate

假设我有这个模型:

class Student(models.Model):
    class_name = models.CharField()
    mark = models.IntegerField()

我想让所有同班同学中mark最高的学生。我可以让所有班级中mark最高的学生像this post中提到的那样。但是我希望所有班级中mark 最高的学生,如下所示:

Student.objects.annotate(
    highest_mark_in_class=Max(
        Students.objects.filter(class_name=F('class_name'))
        .filter(mark=highest_mark_in_class)
    )
)

我可以使用for循环执行此操作,但使用大型数据库for循环相当慢。我不知道是否可以在一行中写下这样的查询?

1 个答案:

答案 0 :(得分:0)

您必须使用2个查询:

import operator
from functools import reduce
from django.db.models import Max, Q

best_marks = Student.objects.values('class_name').annotate(mark=Max('mark'))
q_object = reduce(operator.or_, (Q(**x) for x in best_marks))
queryset = Student.objects.filter(q_object)

第一个查询获取每个类的最佳标记列表。

第二个查询让所有学生在标记和类匹配列表中的一个项目。

请注意,如果您拨打.annotate(best_mark=Max('mark'))而不是.annotate(mark=Max('mark')),则在将字典传递给{之前,您需要做一些额外的工作才能将best_mark重命名为mark {1}}对象。虽然Q非常方便。