Make offset_cutoff a class attribute in CursorPagination so that it can be easily overridden in subclasses (#4212)

This commit is contained in:
Rowan Seymour 2016-06-23 11:37:15 +02:00 committed by Tom Christie
parent 879652ec2e
commit 36ca4b8e06

View File

@ -407,7 +407,7 @@ class LimitOffsetPagination(BasePagination):
class CursorPagination(BasePagination): class CursorPagination(BasePagination):
""" """
The cursor pagination implementation is neccessarily complex. The cursor pagination implementation is necessarily complex.
For an overview of the position/offset style we use, see this post: For an overview of the position/offset style we use, see this post:
http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api
""" """
@ -417,6 +417,12 @@ class CursorPagination(BasePagination):
ordering = '-created' ordering = '-created'
template = 'rest_framework/pagination/previous_and_next.html' template = 'rest_framework/pagination/previous_and_next.html'
# The offset in the cursor is used in situations where we have a
# nearly-unique index. (Eg millisecond precision creation timestamps)
# We guard against malicious users attempting to cause expensive database
# queries, by having a hard cap on the maximum possible size of the offset.
offset_cutoff = 1000
def paginate_queryset(self, queryset, request, view=None): def paginate_queryset(self, queryset, request, view=None):
self.page_size = self.get_page_size(request) self.page_size = self.get_page_size(request)
if not self.page_size: if not self.page_size:
@ -647,18 +653,12 @@ class CursorPagination(BasePagination):
if encoded is None: if encoded is None:
return None return None
# The offset in the cursor is used in situations where we have a
# nearly-unique index. (Eg millisecond precision creation timestamps)
# We guard against malicious users attempting to cause expensive database
# queries, by having a hard cap on the maximum possible size of the offset.
OFFSET_CUTOFF = 1000
try: try:
querystring = b64decode(encoded.encode('ascii')).decode('ascii') querystring = b64decode(encoded.encode('ascii')).decode('ascii')
tokens = urlparse.parse_qs(querystring, keep_blank_values=True) tokens = urlparse.parse_qs(querystring, keep_blank_values=True)
offset = tokens.get('o', ['0'])[0] offset = tokens.get('o', ['0'])[0]
offset = _positive_int(offset, cutoff=OFFSET_CUTOFF) offset = _positive_int(offset, cutoff=self.offset_cutoff)
reverse = tokens.get('r', ['0'])[0] reverse = tokens.get('r', ['0'])[0]
reverse = bool(int(reverse)) reverse = bool(int(reverse))