3

QuerySet のランキングを効率的に実行しようとしています (QuerySet を維持して、filter 関数と order_by 関数を保持できるようにします) が、QuerySet を反復処理してランクを付ける以外の方法を見つけることができないようです。必要がなければ、モデルにランクを追加したくありません。

SQLクエリを介して必要な値を取得する方法は知っていますが、それをDjangoに変換できないようです:

SET @rank = 0, @prev_val = NULL;
SELECT rank, name, school, points FROM
    (SELECT @rank := IF(@prev_val = points, @rank, @rank+1) AS rank, @prev_val := points, points, CONCAT(users.first_name, ' ', users.last_name) as name, school.name as school
    FROM accounts_userprofile
        JOIN schools_school school ON school_id = school.id
        JOIN auth_user users ON user_id = users.id
    ORDER BY points DESC) as profile
ORDER BY rank DESC

QuerySet を反復処理して「ランク」を手動で追加し、結果をさらにフィルター処理すると、「ランク」が消えてしまうことがわかりました。リストに変換しない限り (フィルター処理と並べ替えが少し面倒でした)。私の QuerySet にランクを追加するために考えられる他の方法はありますか? 上記のクエリを実行して、フィルターと order_by 関数をそのまま使用して QuerySet を取得する方法はありますか? 私は現在、DjangoでjQuery DataTablesを使用して、ページネーション付きのリーダーボードを生成しています(これが、フィルタリングとorder_byを保持する必要がある理由です)。

前もって感謝します!質問を正しく投稿しなかった場合は申し訳ありません - どんな助けでも大歓迎です。

4

2 に答える 2

0

生の SQL を見ると、ロジックに特別なものは見当たりません。同じポイント値を同じランクに縮小しながら、1 からのカウンターでポイント順に並べ替えられた結合のすべての SQL 行を単純に列挙しています。

私の提案は、raw() または extra() メソッドを使用するカスタム マネージャーを作成することです。あなたのマネージャーでは、すべてのモデル インスタンスで python の enumerate を使用し、以前にpoints. もちろん、ポイントの現在の最大値を保持し、同じ量のポイントがある場合に enumerate が返すものをオーバーライドする必要があります。似たような例については、こちらをご覧ください。

次に、次のようなことができます。

YourQuerySet.objects.with_rankings().all()
于 2012-06-21T12:23:26.780 に答える
0

私はそれを自分で使用したことはありませんが、extra()メソッドを使用してそれを行うことができると確信しています。

于 2012-06-21T02:21:02.907 に答える