2016-06-28 10 views
1

を持っているすべてのオブジェクト間のフィールドの最大値が、私はこのモデルがあると返す関数に注釈を付けますクラス。 this postで言及されているように、すべてのクラスで最高のmarkの生徒を得ることができます。しかし、私は彼らのクラスで最高markを持っているすべての学生、このような何かしたい:Djangoは機能

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

あなたはそのために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) 

最初のクエリは、各クラスのために最良のマークのリストを取得します。

2番目のクエリでは、マークとクラスがリストの1つのアイテムと一致するすべての生徒を取得します。あなたが.annotate(best_mark=Max('mark'))代わりの.annotate(mark=Max('mark'))を呼び出す場合、あなたは前Qオブジェクトにdictionnaryを渡すにmarkとしてbest_markの名前を変更するには、いくつかの余分な作業を行わなければならないことに

は注意してください。 Q(**x)はかなり便利ですが。

関連する問題