Python Django Rest Framework UnorderedObjectListWarning


82

Django 1.10.4から1.11.1にアップグレードしましたが、テストを実行すると突然、次のようなメッセージが大量に表示されます。

lib/python3.5/site-packages/rest_framework/pagination.py:208:
UnorderedObjectListWarning: 
Pagination may yield inconsistent results with an unordered object_list: 
<QuerySet [<Group: Requester>]>
paginator = self.django_paginator_class(queryset, page_size)

私はそれをDjangoページネーションモジュールまでさかのぼりました:https//github.com/django/django/blob/master/django/core/paginator.py#L100

それは私のクエリセットコードに関連しているようです:

return get_user_model().objects.filter(id=self.request.user.id)

この警告の詳細を確認するにはどうすればよいですか?order_by(id)すべてのフィルターの最後にを追加する必要があるようですが、order_byを追加する必要があるコードが見つからないようです(警告はスタックトレースを返さないため、テスト中にランダムに発生するため)実行)。

ありがとう!

編集:

したがって、@ KlausDを使用します。冗長性のヒント、このエラーの原因となるテストを調べました。

response = self.client.get('/api/orders/')

これはに行きますOrderViewSetが、get_querysetのいずれもそれを引き起こさず、シリアライザークラスの何もそれを引き起こしません。同じコードを使用して/ api / ordersを取得する他のテストがありますが、それらはそれを引き起こしません.... get_querysetの後にDRFは何をしますか?

https://github.com/encode/django-rest-framework/blob/master/rest_framework/pagination.py#L166

ページネーションにトレースバックを入れると、django restフレームワークに関連するものがたくさんありますが、どのクエリが注文警告をトリガーしているかを示すものは何もありません。


1
通常、警告の原因となるテストの名前で簡単に見つけることができます。冗長性のあるテストを実行することをお勧めします(-v 2ほとんどのテストランナーで)
Klaus D.

@KlausDに感謝します。それは役に立つリマインダーです。
Denise Mauldin 2017年

1
あなたがしているが、offsetしてlimitいないクエリをorder_by
探します

@gipsyに感謝します。私は....のもののいずれかを持っていない
デニス・モールディン

回答:


129

したがって、このIを固定するために、すべての見つけなければならなかったalloffsetfilter、およびlimit句をして追加しorder_by、それらに句を。デフォルトの順序を追加して修正したもの:

class Meta:
   ordering = ['-id']

Django Rest FrameworkのViewSet(app / apiviews.py)でget_queryset、デフォルトの順序を追加しても機能しないようだったため、すべてのメソッドを更新する必要がありました。

これが他の誰かに役立つことを願っています。:)


2
素晴らしい、DRFが注文のモデルを読み取ることも知らなかった<3
Amir Savand 2018年

モデルにはデフォルトの順序がありますが、それでもこの警告が表示されます:|
アリエル

私の間違い。親クラスで順序付けを行いましたが、ドキュメント説明されているように適切にサブクラス化せずにMeta属性をオーバーライドしていました。また、子クラスのMetaでは順序付けがなかったため、親からの値が失われました。
アリエル

追加すること-ordering = ['-id']降順で注文クエリを。
エルロンドは

49

view.pyでobjects.all()を使用すると、この警告が表示されていました。

profile_list = Profile.objects.all()
paginator = Paginator(profile_list, 25)

これを修正するために、コードを次のように変更しました。

profile_list = Profile.objects.get_queryset().order_by('id')
paginator = Paginator(profile_list, 25)

1
私はそれがあるべきだと思うProfile.objects.all().order_by('id')、少なくとも...私のために動作する、そうでなければ私が取得AttributeError: type object 'Profile' has no attribute 'get_queryset'
radtek

8

新しい開発に更新された答えを与えましょう...

https://code.djangoproject.com/ticket/6089

Userモデルのデフォルトの順序はDjangoで削除されました。アップグレードのためにこのページが表示された場合は、この変更に関連している可能性があります。

あなたが扱っているかもしれないこの問題の2つのバージョンがあります。

  1. 独自のモデルには、デフォルトの順序がありませんMeta(承認された回答を参照)
  2. デフォルトの順序がない依存関係として使用しているアプリのモデルを使用しています

文字通り、DjangoUserモデル自体は順序に準拠していないため、これらの依存関係のメンテナーにデフォルトの順序を設定するように依頼しても、2番目のシナリオを解決できないことは明らかです。さて、今度は、使用しているモデルをオーバーライドする必要があります(良いアイデアの場合もありますが、そのような小さな問題に対処するには適していません)。

したがって、ビューレベルで対処する必要があります。また、適用した順序付けフィルタークラスとうまく連携する何かをしたいと思います。そのためには、ビューのorderingパラメータを設定します。

class Reviewers(ListView):
    model = User
    paginate_by = 50
    ordering = ['username']

Djangoリストビューモデルの並べ替えはありますか?も参照してください



0

代わりに、モデルメタクラスを更新してください。

class UsefulModel(models.Model):
    
    class Meta:
        ordering='-created' # for example

以前にAlanSEのアドバイスに従って、ビュー属性「ordering」からの順序をオーバーライドすることもできます。

class UsefulView(ListView):
    ordering = ['-created']

0

私の場合、のorder_by('id')代わりに追加する必要がありましたordering

class IntakeCaseViewSet(viewsets.ModelViewSet):
    schema = None
    queryset = IntakeCase.objects.all().order_by('id')

-2

これを含めることは私にとってはうまくいきませんでした。

class Meta:
   ordering = ['-id']

しかし、get_queryset(self)を変更し、.order_by( 'id')でリストを並べ替えました。フィルターを使っているのでうまくいったのかもしれませんが、わかりません

class MyView(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializerSerializer

    def get_queryset(self):
        user = self.request.user
        return MyModel.objects.filter(owner=user).order_by('id')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.