allow setting a custom Django Paginator in pagination.PageNumberPagination

This commit is contained in:
Denis Cornehl 2015-11-13 16:02:19 +01:00
parent 4eef2ea21e
commit 3806af3d15
3 changed files with 63 additions and 1 deletions

View File

@ -95,6 +95,7 @@ The `PageNumberPagination` class includes a number of attributes that may be ove
To set these attributes you should override the `PageNumberPagination` class, and then enable your custom pagination class as above.
* `django_paginator_class` - The Django Paginator class to use. Default is `django.core.paginator.Paginator`, which should be fine for most usecases.
* `page_size` - A numeric value indicating the page size. If set, this overrides the `PAGE_SIZE` setting. Defaults to the same value as the `PAGE_SIZE` settings key.
* `page_query_param` - A string value indicating the name of the query parameter to use for the pagination control.
* `page_size_query_param` - If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults to `None`, indicating that the client may not control the requested page size.

View File

@ -168,6 +168,8 @@ class PageNumberPagination(BasePagination):
# Defaults to `None`, meaning pagination is disabled.
page_size = api_settings.PAGE_SIZE
django_paginator_class = DjangoPaginator
# Client can control the page using this query parameter.
page_query_param = 'page'
@ -194,7 +196,7 @@ class PageNumberPagination(BasePagination):
if not page_size:
return None
paginator = DjangoPaginator(queryset, page_size)
paginator = self.django_paginator_class(queryset, page_size)
page_number = request.query_params.get(self.page_query_param, 1)
if page_number in self.last_page_strings:
page_number = paginator.num_pages

View File

@ -2,6 +2,7 @@
from __future__ import unicode_literals
import pytest
from django.core.paginator import Paginator as DjangoPaginator
from rest_framework import (
exceptions, filters, generics, pagination, serializers, status
@ -249,6 +250,64 @@ class TestPageNumberPagination:
self.paginate_queryset(request)
class TestPageNumberPaginationOverride:
"""
Unit tests for `pagination.PageNumberPagination`.
the Django Paginator Class is overridden.
"""
def setup(self):
class OverriddenDjangoPaginator(DjangoPaginator):
# override the count in our overriden Django Paginator
# we will only return one page, with one item
count = 1
class ExamplePagination(pagination.PageNumberPagination):
django_paginator_class = OverriddenDjangoPaginator
page_size = 5
self.pagination = ExamplePagination()
self.queryset = range(1, 101)
def paginate_queryset(self, request):
return list(self.pagination.paginate_queryset(self.queryset, request))
def get_paginated_content(self, queryset):
response = self.pagination.get_paginated_response(queryset)
return response.data
def get_html_context(self):
return self.pagination.get_html_context()
def test_no_page_number(self):
request = Request(factory.get('/'))
queryset = self.paginate_queryset(request)
content = self.get_paginated_content(queryset)
context = self.get_html_context()
assert queryset == [1]
assert content == {
'results': [1, ],
'previous': None,
'next': None,
'count': 1
}
assert context == {
'previous_url': None,
'next_url': None,
'page_links': [
PageLink('http://testserver/', 1, True, False),
]
}
assert not self.pagination.display_page_controls
assert isinstance(self.pagination.to_html(), type(''))
def test_invalid_page(self):
request = Request(factory.get('/', {'page': 'invalid'}))
with pytest.raises(exceptions.NotFound):
self.paginate_queryset(request)
class TestLimitOffset:
"""
Unit tests for `pagination.LimitOffsetPagination`.