Python Django Rest Framework UnorderedObjectListWarning


88

Я обновился с 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, но не вызывают этого .... Что делает DRF после get_queryset?

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

Если я помещаю трассировку в разбиение на страницы, я получаю целую кучу вещей, связанных с фреймворком django rest, но ничего, что указывает на то, какой из моих запросов вызывает предупреждение о порядке.


1
Обычно его легко найти по названию теста, вызывающего предупреждение. Возможно, вы захотите запустить тесты с -v 2
Клаус Д.

Спасибо @KlausD. это полезное напоминание.
Дениз Молдин

1
Ищет запросы, где ты делаешь offsetа, limitа нетorder_by
цыганка

Спасибо @gipsy. У меня их нет ....
Дениз Молдин

Ответы:


138

Поэтому для того , чтобы исправить это , я должен был найти все all, offset, filterи limitположений и добавить order_byпункт к ним. Некоторые я исправил, добавив порядок по умолчанию:

class Meta:
   ordering = ['-id']

В ViewSets для Django Rest Framework (app / apiviews.py) мне пришлось обновить все get_querysetметоды, так как добавление порядка по умолчанию, похоже, не сработало.

Надеюсь, это поможет кому-то другому. :)


2
Потрясающе, не знал, что DRF тоже читает модель для заказа <3
Амир Саванд

У меня в модели есть порядок по умолчанию, но я все равно получаю это предупреждение: |
Ариэль

Моя ошибка. У меня был порядок в родительском классе, но я переопределял атрибут Meta без должного подкласса, как описано в документации , а в дочернем классе Meta у меня не было упорядочивания, поэтому значение из родительского элемента было потеряно.
Ариэль

1
Обратите внимание, что добавление -в ordering = ['-id']запрос упорядочивает ваш запрос в порядке убывания.
Элронд поддерживает Монику

50

Я получал это предупреждение, когда использовал objects.all () в своем view.py

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

9

Позвольте мне дать обновленный ответ на новые события ...

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

Порядок Userмодели по умолчанию был удален в Django. Если вы оказались на этой странице из-за обновления, скорее всего, это связано с этим изменением.

Есть 2 версии этой проблемы, с которыми вы можете столкнуться.

  1. ваша собственная модель не имеет порядка по умолчанию Meta(см. принятый ответ)
  2. вы используете модель из приложения, которое вы используете в качестве зависимости, у которой нет порядка по умолчанию

Поскольку буквально сама Userмодель Django не подчиняется порядку, совершенно очевидно, что второй сценарий не может быть разрешен, если попросить разработчиков этих зависимостей установить порядок по умолчанию. Хорошо, теперь вам нужно либо переопределить используемую модель для того, что вы делаете (иногда это хорошая идея, но не подходит для решения такой незначительной проблемы).

Итак, вам остается обратиться к нему на уровне представления. Вы также хотите сделать что-то, что будет хорошо работать с любым классом упорядочивающего фильтра, который вы применили. Для этого установите orderingпараметр представления.

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

Также см. Есть ли сортировка модели Django List View?



1

В моем случае мне пришлось добавить order_by('id')вместо ordering.

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

0

Вместо этого обновите мета-класс модели.

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

вы все еще можете переопределить порядок из атрибута представления 'ordering', как ранее рекомендовалось AlanSE .

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

-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')
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.