Python Django Rest Framework UnorderedObjectListWarning
I upgraded from Django 1.10.4 to 1.11.1 and all of a sudden I'm getting a ton of these messages when I run my tests:
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)
I've traced that back to the Django Pagination module: https://github.com/django/django/blob/master/django/core/paginator.py#L100
It seems to be related to my queryset code:
return get_user_model().objects.filter(id=self.request.user.id)
How can I find more details on this warning? It seems to be that I need to add a order_by(id)
on the end of every filter, but I can't seem to find which code needs the order_by added (because the warning doesn't return a stack trace and so it happens randomly during my test run).
Thanks!
Edit:
So by using @KlausD. verbosity tip, I looked at a test causing this error:
response = self.client.get('/api/orders/')
This goes to OrderViewSet
but none of the things in get_queryset cause it and nothing in serializer class causes it. I have other tests that use the same code to get /api/orders and those don't cause it.... What does DRF do after get_queryset?
https://github.com/encode/django-rest-framework/blob/master/rest_framework/pagination.py#L166
If I put a traceback into pagination then I get a whole bunch of stuff related to django rest framework but nothing that points back to which of my queries is triggering the order warning.
Solution 1:
So in order to fix this I had to find all of the all
, offset
, filter
, and limit
clauses and add a order_by
clause to them. Some I fixed by adding a default ordering:
class Meta:
ordering = ['-id']
In the ViewSets for Django Rest Framework (app/apiviews.py) I had to update all of the get_queryset
methods as adding a default ordering didn't seem to work.
Hope this helps someone else. :)
Solution 2:
I was getting this warning when i used objects.all() in my view.py
profile_list = Profile.objects.all()
paginator = Paginator(profile_list, 25)
to fix this i changed my code to :
profile_list = Profile.objects.get_queryset().order_by('id')
paginator = Paginator(profile_list, 25)