Django комментирует функцию, которая возвращает максимум поля среди всех объектов, имеющих функцию
Предположим, что у меня есть эта модель:
class Student(models.Model):
class_name = models.CharField()
mark = models.IntegerField()
И я хочу, чтобы все студенты, которые имеют самые высокие mark
в своем классе. Я могу получить студента, который имеет самый высокий mark
во всех классах, как это упоминается в этом посте. Но я хочу, чтобы все студенты, которые имеют самый высокий 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 ответ
Для этого вам нужно будет использовать 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
до передачи словаря в Q
объект. В то время как Q(**x)
это довольно удобно.