Python Django Rest Framework UnorderedObjectListWarning


82

Tôi đã nâng cấp từ Django 1.10.4 lên 1.11.1 và đột nhiên tôi nhận được rất nhiều thông báo sau khi chạy thử nghiệm của mình:

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)

Tôi đã truy nguyên điều đó trở lại mô-đun Phân trang Django: https://github.com/django/django/blob/master/django/core/paginator.py#L100

Nó dường như liên quan đến mã bộ truy vấn của tôi:

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

Làm cách nào để tìm thêm thông tin chi tiết về cảnh báo này? Có vẻ như tôi cần thêm dấu order_by(id)vào cuối mỗi bộ lọc, nhưng dường như tôi không thể tìm thấy mã nào cần thêm order_by (vì cảnh báo không trả lại dấu vết ngăn xếp và vì vậy nó xảy ra ngẫu nhiên trong quá trình thử nghiệm của tôi chạy).

Cảm ơn!

Biên tập:

Vì vậy, bằng cách sử dụng @KlausD. mẹo chi tiết, tôi đã xem xét một bài kiểm tra gây ra lỗi này:

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

Điều này xảy ra OrderViewSetnhưng không có thứ nào trong get_queryset gây ra nó và không có thứ gì trong lớp serializer gây ra nó. Tôi có các thử nghiệm khác sử dụng cùng một mã để nhận / api / các đơn đặt hàng và những thử nghiệm đó không gây ra lỗi đó .... DRF làm gì sau get_queryset?

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

Nếu tôi đặt dấu vết vào phân trang thì tôi nhận được một loạt nội dung liên quan đến khung phần còn lại django nhưng không có gì chỉ ra truy vấn nào của tôi đang kích hoạt cảnh báo đơn hàng.


1
Thông thường nó sẽ dễ dàng tìm thấy theo tên của xét nghiệm gây ra cảnh báo. Bạn có thể muốn chạy thử nghiệm với độ chi tiết ( -v 2trên hầu hết những người chạy thử nghiệm)
Klaus D.

Cảm ơn @KlausD. đó là một lời nhắc nhở hữu ích.
Denise Mauldin

1
Tìm kiếm các truy vấn mà bạn đang thực hiện offsetlimitnhưng khôngorder_by
gipsy

Cảm ơn @gipsy. Tôi không có bất kỳ cái nào trong số đó ....
Denise Mauldin

Câu trả lời:


129

Vì vậy, để sửa chữa tôi này đã phải tìm tất cả các all, offset, filter, và limitcác điều khoản và thêm một order_bykhoản cho họ. Một số tôi đã sửa bằng cách thêm thứ tự mặc định:

class Meta:
   ordering = ['-id']

Trong ViewSets cho Django Rest Framework (app / apiviews.py), tôi đã phải cập nhật tất cả các get_querysetphương pháp vì việc thêm thứ tự mặc định dường như không hoạt động.

Hy vọng điều này sẽ giúp người khác. :)


2
Tuyệt vời, không biết rằng DRF đọc mô hình để đặt hàng quá <3
Amir Savand

Tôi có một thứ tự mặc định trong mô hình của mình nhưng tôi vẫn nhận được cảnh báo này: |
Ariel

Lỗi của tôi. Tôi đã sắp xếp thứ tự trong lớp cha, nhưng tôi đã ghi đè thuộc tính Meta mà không phân lớp chính xác nó như được mô tả trong tài liệu và trong lớp con 'Meta, tôi không có thứ tự, vì vậy giá trị từ cha mẹ bị mất.
Ariel

Lưu ý rằng việc thêm các -trong ordering = ['-id']lệnh truy vấn của bạn theo thứ tự giảm dần.
Elrond ủng hộ Monica

49

Tôi nhận được cảnh báo này khi tôi sử dụng objects.all () trong view.py

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

để khắc phục điều này, tôi đã thay đổi mã của mình thành:

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

1
Tôi nghĩ rằng nó phải được Profile.objects.all().order_by('id').. ít nhất là làm việc cho tôi, nếu không tôi có đượcAttributeError: type object 'Profile' has no attribute 'get_queryset'
radtek

8

Hãy để tôi đưa ra câu trả lời được cập nhật về những phát triển mới ...

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

Thứ tự mặc định của Usermô hình đã bị xóa trong Django. Nếu bạn thấy mình ở trang này do nâng cấp, thì rất có thể nó được kết nối với thay đổi này.

Có 2 phiên bản của sự cố này mà bạn có thể phải đối phó.

  1. mô hình của riêng bạn không có thứ tự mặc định trong nó Meta(xem câu trả lời được chấp nhận)
  2. bạn đang sử dụng một mô hình từ một ứng dụng mà bạn đang sử dụng làm phụ thuộc không có thứ tự mặc định

Userbản thân mô hình Django theo nghĩa đen không tuân theo thứ tự, nên rất rõ ràng rằng kịch bản thứ hai không thể được giải quyết bằng cách yêu cầu những người bảo trì các phụ thuộc đó đặt theo thứ tự mặc định. Được rồi, vì vậy bây giờ bạn phải ghi đè mô hình đang được sử dụng cho bất kỳ việc gì của bạn (đôi khi là một ý tưởng tốt, nhưng không tốt để giải quyết một vấn đề nhỏ như vậy).

Vì vậy, bạn còn lại với việc giải quyết nó ở cấp độ xem. Bạn cũng muốn làm điều gì đó sẽ phù hợp với bất kỳ lớp bộ lọc thứ tự nào mà bạn đã áp dụng. Đối với điều đó, hãy đặt orderingtham số của chế độ xem .

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

Cũng xem Có sắp xếp mô hình Django List View không?



0

Thay vào đó, hãy cập nhật lớp meta mô hình.

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

bạn vẫn có thể ghi đè thứ tự từ thuộc tính xem 'đặt hàng' Theo lời khuyên của AlanSE trước đây.

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

0

Trong trường hợp của tôi, tôi đã phải thêm order_by('id')thay vì ordering.

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

-2

Bao gồm cả điều này không làm việc cho tôi.

class Meta:
   ordering = ['-id']

Nhưng việc thay đổi get_queryset (self) và sắp xếp danh sách bằng .order_by ('id') đã làm được. Có thể hiệu quả vì tôi đang sử dụng bộ lọc, tôi không biết

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')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.