2013-04-21 25 views
5

私のサイト(UserProfile)のすべてのユーザーのモデルがあり、各プロファイルにはpointsという名前のフィールドが含まれています。Djangoを使用したリーダーボードの実装

ポイントでソートしている間に、現在のユーザーから-5 +5ユーザーを取得したいと考えています。どうすればこれを達成できますか?

答えて

3

あなただけの後に2つのクエリは、現在のユーザーの前にユーザー用、およびユーザーのための1つを作ることができます:

  • すべてのユーザーを持つ:これは、2つのクエリの塩基である

    id = current_user.pk 
    points = current_user.profile.points 
    
    before = User.objects.filter(
        Q(profile__points__gt=points) | 
        Q(profile__points=points, pk__lt=id) 
    ).order_by('-profile__points')[:5] 
    
    after = User.objects.filter(
        Q(profile__points__lt=points) | 
        Q(profile__points=points, pk__gt=id) 
    ).order_by('profile__points')[:5] 
    

    現在のユーザよりも大きいスコア、または同じスコアであるが、より低いスコアのpkを含む。

  • 現在のユーザーよりもスコアが低い、またはスコアが同じであるが、より大きいpkを持つすべてのユーザー。

次に、適切な発注と制限で結果を得ることができます。もちろん、pkは、他のファイルに置き換えることも、完全に削除することもできます。後者の場合は、あなたの代わりに(これは単なる一例である)現在のユーザーは常に最初であると考えることができ、クエリは次のようになります。

before = User.objects.filter(
    profile__points__gt=points, 
).order_by('-profile__points')[:5] 

after = User.objects.filter(
    profile__points__lte=points, 
).exclude(pk=id).order_by('profile__points')[:5] 

を別の方法として、リスト内の現在のユーザーのほんのインデックスを取得しますポイントによってソートユーザーで、あなたができる:

id = current_user.pk 
points = current_user.profile.points 
index = User.objects.filter(
    Q(profile__points__gt=points) | 
    Q(profile__points=points, pk__lt=id) 
).count() 

その後、ユーザーのリストは、現在の1を中心とすることは、単に次のようになります。

User.objects.all().order_by('-profile__points', 'pk')[index - 5:index + 6] 

ます場合は、この選択肢は遅くなる可能性が現在のユーザーを評価する前にユーザーのリスト全体が評価されているため、多くのユーザーがいますが、私はこれを検証しませんでした。

+0

に注意してください。どのように私はその順序でユーザーの "場所"を得ることができますか? –

+0

@ Nuno_147現在のものより前のユーザーの数を数えることができます。 –

+0

Q(profile__points__gt =ポイント)| Q(profile__points = points)はQ(profile__points_gte = point)に変更できますか? –

1

私はあなたのポイントが何であるかわからないんだけど、これは単に、以下のようなものに注釈を付けなければなりません...

from django.db.models import Sum, Avg 

UserProfile.objects.annotate(sum_rating=Sum('sum__points')).order_by('-sum_points') 

はあなたがフィルターに注釈変数を使用することができます忘れないでください。

更新: ポイントでわずかため、動作する必要があることを-

UserProfile.objects.filter(whatever here).order_by('-points')[:5] 

または

.order_by('points')[:5] 
+0

申し訳ありませんが、私はポイントを計算しているので、注釈は必要ありません。ここでの課題は、ユーザーポイントの+ 5-5をどのように取得する必要があるかです。私はリーダーボードに彼の所在地を加え、彼の前に5を、彼の後に5を追加したい。 –

+0

次に、ポイントでフィルタリングし、順番に並べ替えます。これらの結果の上位5つを取得できます。最後の5つは降順で行います。 –

+0

私の質問は上からではなく、特定のユーザーからのものでした。私は、順序でユーザーを探し、+5 -5を取得する必要があります。 –

関連する問題