Python Django Rest Framework UnorderedObjectListWarning

Den*_*din 64 python django django-rest-framework

我从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)
Run Code Online (Sandbox Code Playgroud)

我已经追溯到Django Pagination模块:https: //github.com/django/django/blob/master/django/core/paginator.py#L100

它似乎与我的queryset代码有关:

return get_user_model().objects.filter(id=self.request.user.id)
Run Code Online (Sandbox Code Playgroud)

如何找到有关此警告的更多详细信息?似乎我需要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框架相关的内容,但没有任何内容可以指出我的哪些查询触发了订单警告.

Den*_*din 94

因此,为了解决这个问题我必须找到所有的all,offset,filter,以及limit条款和补充order_by条款给他们.有些我通过添加默认排序来修复:

class Meta:
   ordering = ['-id']
Run Code Online (Sandbox Code Playgroud)

在ViewSets for Django Rest Framework(app/apiviews.py)中,我不得不更新所有get_queryset方法,因为添加默认排序似乎不起作用.

希望这有助于其他人.:)

  • 我认为正确的解决方案实际上是*不*在模型上指定默认排序,因为这可能会对将来使用该模型的其他任何事情产生严重的副作用。可能会困扰您的副作用的一个示例是查询规划器决定使用不正确的索引来确定排序优先级而不是过滤。这可能会对较大的表产生巨大的性能影响。相反,您应该在 drf 视图上指定默认排序,或者特别是在作者的情况下,您返回的查询应该指定“order_by()”。 (4认同)
  • 太棒了,不知道DRF也会读取订单模型&lt;3 (2认同)
  • **注意**,在 `ordering = ['-id']` 中添加 `-` 以降序排列您的查询。 (2认同)

Raj*_*rma 34

当我在view.py中使用了objects.all()时,我收到了这个警告

profile_list = Profile.objects.all()
paginator = Paginator(profile_list, 25)
Run Code Online (Sandbox Code Playgroud)

解决这个问题我改变了我的代码:

profile_list = Profile.objects.get_queryset().order_by('id')
paginator = Paginator(profile_list, 25)
Run Code Online (Sandbox Code Playgroud)

  • 我认为它应该是 `Profile.objects.all().order_by('id')` ..至少对我有用,否则我会得到 `AttributeError: type object 'Profile' has no attribute 'get_queryset'` (2认同)

Ala*_*nSE 10

让我根据新的发展给出一个更新的答案......

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

User模型的默认排序已在 Django 中删除。如果您因为升级而出现在此页面,则很可能与此更改有关。

您可能正在处理这个问题的 2 个版本。

  1. 您自己的模型中没有默认排序Meta(请参阅已接受的答案)
  2. 您正在使用来自您用作依赖项的应用程序的模型,该模型没有默认排序

由于从字面上看 DjangoUser模型本身并不遵守顺序,很明显,通过要求这些依赖项的维护者设置默认顺序无法解决第二种情况。好的,所以现在您要么必须覆盖用于您所做的任何事情的模型(有时是个好主意,但不适合解决这样一个小问题)。

因此,您只能在视图级别解决它。您还希望做一些可以与您应用的任何排序过滤器类很好地配合的事情。为此,设置视图的ordering参数。

class Reviewers(ListView):
    model = User
    paginate_by = 50
    ordering = ['username']
Run Code Online (Sandbox Code Playgroud)

另请参阅是否有 Django 列表视图模型排序?


Pau*_*ber 7

就我而言,我不得不添加order_by('id')而不是ordering.

class IntakeCaseViewSet(viewsets.ModelViewSet):
    schema = None
    queryset = IntakeCase.objects.all().order_by('id')
Run Code Online (Sandbox Code Playgroud)