【问题标题】:django annotate a function that returns the maximum of a field among all objects that has a featuredjango注释一个函数,该函数返回所有具有特征的对象中字段的最大值
【发布时间】:2016-10-30 18:30:42
【问题描述】:

假设我有这个模型:

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 循环相当慢。不知道这样的查询能不能写成一行?

【问题讨论】:

    标签: python django django-orm django-annotate


    【解决方案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')),则在将字典传递给Q 对象之前,您必须做一些额外的工作才能将best_mark 重命名为mark。虽然Q(**x) 很方便。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      • 2019-09-24
      • 1970-01-01
      相关资源
      最近更新 更多