Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 11 additions & 26 deletions rest_framework/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ def paginate_queryset(self, queryset, request, view=None):
return None

self.base_url = request.build_absolute_uri()
self.ordering = self.get_ordering(request, queryset, view)
self.ordering = self.get_ordering()

self.cursor = self.decode_cursor(request)
if self.cursor is None:
Expand All @@ -624,10 +624,11 @@ def paginate_queryset(self, queryset, request, view=None):
(offset, reverse, current_position) = self.cursor

# Cursor pagination always enforces an ordering.
if reverse:
queryset = queryset.order_by(*_reverse_ordering(self.ordering))
else:
queryset = queryset.order_by(*self.ordering)
if not queryset.ordered:
if reverse:
queryset = queryset.order_by(*_reverse_ordering(self.ordering))
else:
queryset = queryset.order_by(*self.ordering)

# If we have a cursor with a fixed position then filter by that.
if current_position is not None:
Expand Down Expand Up @@ -801,41 +802,25 @@ def get_previous_link(self):
cursor = Cursor(offset=offset, reverse=True, position=position)
return self.encode_cursor(cursor)

def get_ordering(self, request, queryset, view):
def get_ordering(self):
"""
Return a tuple of strings, that may be used in an `order_by` method.
"""
# The default case is to check for an `ordering` attribute
# on this pagination instance.
ordering = self.ordering

ordering_filters = [
filter_cls for filter_cls in getattr(view, 'filter_backends', [])
if hasattr(filter_cls, 'get_ordering')
]

if ordering_filters:
# If a filter exists on the view that implements `get_ordering`
# then we defer to that filter to determine the ordering.
filter_cls = ordering_filters[0]
filter_instance = filter_cls()
ordering_from_filter = filter_instance.get_ordering(request, queryset, view)
if ordering_from_filter:
ordering = ordering_from_filter

assert ordering is not None, (
assert self.ordering is not None, (
'Using cursor pagination, but no ordering attribute was declared '
'on the pagination class.'
)
assert '__' not in ordering, (
assert '__' not in self.ordering, (
'Cursor pagination does not support double underscore lookups '
'for orderings. Orderings should be an unchanging, unique or '
'nearly-unique field on the model, such as "-created" or "pk".'
)

assert isinstance(ordering, (str, list, tuple)), (
assert isinstance(self.ordering, (str, list, tuple)), (
'Invalid ordering. Expected string or tuple, but got {type}'.format(
type=type(ordering).__name__
type=type(self.ordering).__name__
)
)

Expand Down
Loading