Python Django Rest Framework UnorderedObjectListWarning


88

Django 1.10.4'ten 1.11.1'e yükselttim ve aniden testlerimi çalıştırdığımda şu mesajlardan bir ton alıyorum:

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)

Bunu Django Sayfalandırma modülüne kadar takip ettim: https://github.com/django/django/blob/master/django/core/paginator.py#L100

Sorgu seti kodumla ilgili görünüyor:

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

Bu uyarı hakkında nasıl daha fazla ayrıntı bulabilirim? Görünüşe order_by(id)göre her filtrenin sonuna bir eklemem gerekiyor , ancak hangi kodun order_by eklenmesini gerektirdiğini bulamıyorum (çünkü uyarı bir yığın izleme döndürmüyor ve bu nedenle testim sırasında rastgele oluyor Çalıştırmak).

Teşekkürler!

Düzenle:

Yani @KlausD kullanarak. ayrıntı ipucu, bu hataya neden olan bir teste baktım:

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

Bu gider OrderViewSetancak get_queryset içindeki hiçbir şey buna neden olmaz ve serileştirici sınıfındaki hiçbir şey buna neden olmaz. / Api / siparişlerini almak için aynı kodu kullanan ve buna neden olmayan başka testlerim var .... get_queryset'ten sonra DRF ne yapar?

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

Sayfalandırmaya bir geri bildirim koyarsam, django dinlenme çerçevesi ile ilgili bir sürü şey elde ederim, ancak sorgularımdan hangisinin sipariş uyarısını tetiklediğini gösteren hiçbir şey yok.


1
Genellikle uyarıya neden olan testin adına göre bulmak kolay olmalıdır. Ayrıntılı testler yapmak isteyebilirsiniz ( -v 2çoğu test koşucusunda)
Klaus D.

Teşekkürler @KlausD. bu yararlı bir hatırlatmadır.
Denise Mauldin

1
Sorguları için görünüyor bir işin var burada offsetve limitancakorder_by
çingene

Teşekkürler @gipsy. Bende bunlardan hiçbiri yok ....
Denise Mauldin

Yanıtlar:


138

Yani bu I düzeltmek için tüm bulmak zorunda all, offset, filterve limitmaddelerine ve eklemek order_byonlara maddesini. Bazılarını varsayılan bir sıralama ekleyerek düzelttim:

class Meta:
   ordering = ['-id']

Django Rest Framework için ViewSets'te (app / apiviews.py), get_querysetvarsayılan bir sıralama eklemek işe yaramadığı için tüm yöntemleri güncellemem gerekiyordu.

Umarım bu başka birine yardımcı olur. :)


2
Harika, DRF'nin sipariş için modeli de okuduğunu bilmiyordum <3
Amir Savand

Modelimde varsayılan bir siparişim var ama yine de şu uyarıyı alıyorum: |
Ariel

Benim hatam. Üst sınıfta sipariş vermiştim, ancak Meta niteliğini belgelerde açıklandığı gibi uygun şekilde alt sınıflara ayırmadan geçersiz kılıyordum ve 'Meta alt sınıfında hiçbir sıralama yoktu, bu nedenle ebeveynden gelen değer kayboldu.
Ariel

1
Not belirtti -içinde ordering = ['-id']azalan düzende emir Sorgunuzla.
Elrond, Monica'yı

50

View.py içinde objects.all () kullandığımda bu uyarıyı alıyordum

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

bunu düzeltmek için kodumu şu şekilde değiştirdim:

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

1
Sanırım öyle olmalı Profile.objects.all().order_by('id').. en azından benim için işe yarıyor, yoksa anlıyorumAttributeError: type object 'Profile' has no attribute 'get_queryset'
radtek

9

Yeni gelişmelere güncellenmiş bir cevap vereyim ...

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

UserModelin varsayılan sıralaması Django'da kaldırıldı. Kendinizi bir yükseltme nedeniyle bu sayfada bulduysanız, büyük olasılıkla bu değişiklikle bağlantılı.

Bu problemin uğraşıyor olabileceğiniz 2 versiyonu vardır.

  1. kendi modelinizin varsayılan bir sıralaması yok Meta(kabul edilen cevaba bakın)
  2. Bağımlılık olarak kullandığınız ve varsayılan sıralaması olmayan bir uygulamanın modelini kullanıyorsunuz

Kelimenin tam anlamıyla Django Usermodelinin kendisi siparişe bağlı olmadığından, ikinci senaryonun bu bağımlılıkların koruyucularından varsayılan bir sıralama yapmalarını isteyerek çözülemeyeceği çok açıktır. Tamam, yani şimdi ne yaparsanız yapın kullanılan modeli geçersiz kılmalısınız (bazen iyi bir fikir, ancak bu kadar küçük bir sorunu ele almak için iyi değil).

Yani bunu görüş seviyesinde ele almakla kaldınız. Ayrıca, uyguladığınız herhangi bir sıralama filtresi sınıfıyla güzelce oynayacak bir şey yapmak istersiniz. Bunun için görünümün orderingparametresini ayarlayın.

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

Ayrıca bkz. Django Liste Görünümü model sıralaması var mı?



1

Benim durumumda, order_by('id')yerine eklemek zorunda kaldım ordering.

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

0

Bunun yerine model meta sınıfını güncelleyin.

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

Daha önce AlanSE tarafından tavsiye edildiği gibi, görünüm özniteliğinden sıralamayı yine de geçersiz kılabilirsiniz .

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

-2

Bu benim için işe yaramadı.

class Meta:
   ordering = ['-id']

Ancak get_queryset (self) 'in değiştirilmesi ve listenin .order_by (' id ') ile sıralanması bunu yaptı. Belki işe yaradı çünkü filtreler kullanıyorum, bilmiyorum

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')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.