6

(id、rank)ペアで構成されるdictがあります。結果のクエリセットがランク(降順)で並べ替えられるように、IDに対してDjangoクエリを実行したいと思います。

クエリセットの取得は簡単です。

rankings = {...}
result = MyModel.objects.filter(id__in=rankings.keys())

答えには、order_byの一部として使用できるある種の注釈が含まれているようですが、そこに到達する方法がわかりません。

編集:これはおいしいAPIパイプラインの一部であるため、結果をQuerySetにする必要があることを忘れました。

4

3 に答える 3

6

Django>1.10およびPostgreSQL>9.5の私のソリューション

from django.db.models import Func, Value, IntegerField, CharField
from django.contrib.postgres.fields import ArrayField


class ArrayPosition(Func):
    function = 'array_position'

    def __init__(self, items, *expressions, **extra):
        if isinstance(items[0], int):
            base_field = IntegerField()
        else:
            base_field = CharField(max_length=max(len(i) for i in items))
        first_arg = Value(list(items), output_field=ArrayField(base_field))
        expressions = (first_arg, ) + expressions
        super().__init__(*expressions, **extra)


pk_list = [234,12,23]
queryset = SomeModel.objects.filter(pk__in=pk_list, ...)\
    .annotate(ordering=ArrayPosition(pk_list, F('pk'), output_field=IntegerField()))\
    .order_by('ordering')
于 2019-04-12T11:21:35.087 に答える
2

このようなもの?

rankings = { 1 : 2, 2: 1, ... } # i.e. { 'id' : 'ranking', ... }
objects = list(MyModel.objects.filter(id__in=rankings.keys()))
objects.sort(key=lambda obj: rankings[obj.id])
于 2012-10-23T22:24:29.683 に答える
0

これを解決するために私が理解できる唯一の方法は、プライマリモデルに関連する新しいランキングモデルを作成することです。各クエリで、ランキングアイテムをそのモデルに挿入し、リレーションを介してorder_byを実行できるようにします。(注釈を使用して学校の記録にランクを追加します。)

class UserSchoolRanking(models.Model):
    user = models.ForeignKey(User)
    school = models.ForeignKey(School)
    rank = models.IntegerField()

bulk_user_school_rank = [UserSchoolRank(user=user, school_id=k, rank=v)
                                         for k, v in rankings.iteritems()]
UserSchoolRank.objects.bulk_create(bulk_user_school_rank)

schools = School.objects.filter(userschoolrank__user=user)\
                .annotate(rank=Min('userschoolrank__rank'))\
                .order_by('-userschoolrank__rank')
于 2012-10-24T01:45:43.650 に答える