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 Pagination模块: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。这是一个有用的提醒。
丹妮丝·莫尔丁

1
查找查询,你正在做的offsetlimit,但没有order_by
吉卜赛

谢谢@吉普赛。我没有这些
。...–丹妮丝·莫尔丁

Answers:


129

因此,为了解决这个问题我必须找到所有的alloffsetfilter,以及limit条款和补充order_by条款给他们。我通过添加默认顺序来解决一些问题:

class Meta:
   ordering = ['-id']

在Django Rest Framework的ViewSets(app / apiviews.py)中,我不得不更新所有get_queryset方法,因为添加默认顺序似乎无效。

希望这对其他人有帮助。:)


2
太棒了,不知道DRF也无法读取订单模型[3
Amir Savand

我的模型中确实有默认顺序,但是仍然收到此警告:|
阿里埃勒

我的错。我在父类中进行了排序,但是我没有按docs中所述正确覆盖Meta属性,而没有正确地对其进行子类化,而在子类的Meta中,我没有排序,因此父级的值丢失了。
阿里尔

请注意,按查询顺序降序添加-in ordering = ['-id']
艾隆(Elrond)

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'
有用

8

让我给出最新进展的答案...

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

User模型的默认排序已在Django中删除。如果您是由于升级而在此页面上找到自己的,则很可能与此更改有关。

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

  1. 您自己的模型没有默认顺序Meta(请参见接受的答案)
  2. 您使用的是应用程序中的模型,您将其用作没有默认顺序的依赖项

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

因此,您只需要在视图级别进行处理即可。您还想做一些可以与您应用的任何排序过滤器类很好地配合的操作。为此,设置视图的ordering参数。

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

另请参阅Django List View模型排序吗?



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')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.