Author: russellm Date: 2010-12-04 22:32:36 -0600 (Sat, 04 Dec 2010) New Revision: 14828
Modified: django/trunk/django/views/generic/list.py django/trunk/docs/ref/class-based-views.txt django/trunk/tests/regressiontests/generic_views/list.py django/trunk/tests/regressiontests/generic_views/urls.py django/trunk/tests/regressiontests/generic_views/views.py Log: Fixed #14773 -- Modified MultipleObjectMixin to allow for custom paginators. Thanks to piquadrat for the report and initial patch. Modified: django/trunk/django/views/generic/list.py =================================================================== --- django/trunk/django/views/generic/list.py 2010-12-05 02:09:29 UTC (rev 14827) +++ django/trunk/django/views/generic/list.py 2010-12-05 04:32:36 UTC (rev 14828) @@ -10,6 +10,7 @@ model = None paginate_by = None context_object_name = None + paginator_class = Paginator def get_queryset(self): """ @@ -32,7 +33,7 @@ Paginate the queryset, if needed. """ if queryset.count() > page_size: - paginator = Paginator(queryset, page_size, allow_empty_first_page=self.get_allow_empty()) + paginator = self.get_paginator(queryset, page_size, allow_empty_first_page=self.get_allow_empty()) page = self.kwargs.get('page', None) or self.request.GET.get('page', 1) try: page_number = int(page) @@ -55,6 +56,12 @@ """ return self.paginate_by + def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True): + """ + Return an instance of the paginator for this view. + """ + return self.paginator_class(queryset, per_page, orphans=orphans, allow_empty_first_page=allow_empty_first_page) + def get_allow_empty(self): """ Returns ``True`` if the view should display empty lists, and ``False`` Modified: django/trunk/docs/ref/class-based-views.txt =================================================================== --- django/trunk/docs/ref/class-based-views.txt 2010-12-05 02:09:29 UTC (rev 14827) +++ django/trunk/docs/ref/class-based-views.txt 2010-12-05 04:32:36 UTC (rev 14828) @@ -305,6 +305,14 @@ expect either a ``page`` query string parameter (via ``GET``) or a ``page`` variable specified in the URLconf. + .. attribute:: paginator_class + + The paginator class to be used for pagination. By default, + :class:`django.core.paginator.Paginator` is used. If the custom paginator + class doesn't have the same constructor interface as + :class:`django.core.paginator.Paginator`, you will also need to + provide an implementation for :meth:`MultipleObjectMixin.get_paginator`. + .. attribute:: context_object_name Designates the name of the variable to use in the context. @@ -329,6 +337,11 @@ pagination. By default this simply returns the value of :attr:`MultipleObjectMixin.paginate_by`. + .. method:: get_paginator(queryset, queryset, per_page, orphans=0, allow_empty_first_page=True) + + Returns an instance of the paginator to use for this view. By default, + instantiates an instance of :attr:`paginator_class`. + .. method:: get_allow_empty() Return a boolean specifying whether to display the page if no objects Modified: django/trunk/tests/regressiontests/generic_views/list.py =================================================================== --- django/trunk/tests/regressiontests/generic_views/list.py 2010-12-05 02:09:29 UTC (rev 14827) +++ django/trunk/tests/regressiontests/generic_views/list.py 2010-12-05 04:32:36 UTC (rev 14828) @@ -2,8 +2,8 @@ from django.test import TestCase from regressiontests.generic_views.models import Author +from regressiontests.generic_views.views import CustomPaginator - class ListViewTests(TestCase): fixtures = ['generic-views-test-data.json'] urls = 'regressiontests.generic_views.urls' @@ -86,6 +86,21 @@ res = self.client.get('/list/authors/paginated/?page=frog') self.assertEqual(res.status_code, 404) + def test_paginated_custom_paginator_class(self): + self._make_authors(7) + res = self.client.get('/list/authors/paginated/custom_class/') + self.assertEqual(res.status_code, 200) + self.assertIsInstance(res.context['paginator'], CustomPaginator) + # Custom pagination allows for 2 orphans on a page size of 5 + self.assertEqual(len(res.context['object_list']), 7) + + def test_paginated_custom_paginator_constructor(self): + self._make_authors(7) + res = self.client.get('/list/authors/paginated/custom_constructor/') + self.assertEqual(res.status_code, 200) + # Custom pagination allows for 2 orphans on a page size of 5 + self.assertEqual(len(res.context['object_list']), 7) + def test_allow_empty_false(self): res = self.client.get('/list/authors/notempty/') self.assertEqual(res.status_code, 200) Modified: django/trunk/tests/regressiontests/generic_views/urls.py =================================================================== --- django/trunk/tests/regressiontests/generic_views/urls.py 2010-12-05 02:09:29 UTC (rev 14827) +++ django/trunk/tests/regressiontests/generic_views/urls.py 2010-12-05 04:32:36 UTC (rev 14828) @@ -117,6 +117,10 @@ views.AuthorList.as_view(context_object_name='object_list')), (r'^list/authors/invalid/$', views.AuthorList.as_view(queryset=None)), + (r'^list/authors/paginated/custom_class/$', + views.AuthorList.as_view(paginate_by=5, paginator_class=views.CustomPaginator)), + (r'^list/authors/paginated/custom_constructor/$', + views.AuthorListCustomPaginator.as_view()), # YearArchiveView # Mixing keyword and possitional captures below is intentional; the views Modified: django/trunk/tests/regressiontests/generic_views/views.py =================================================================== --- django/trunk/tests/regressiontests/generic_views/views.py 2010-12-05 02:09:29 UTC (rev 14827) +++ django/trunk/tests/regressiontests/generic_views/views.py 2010-12-05 04:32:36 UTC (rev 14828) @@ -1,4 +1,5 @@ from django.contrib.auth.decorators import login_required +from django.core.paginator import Paginator from django.core.urlresolvers import reverse from django.utils.decorators import method_decorator from django.views import generic @@ -50,7 +51,24 @@ queryset = Author.objects.all() +class CustomPaginator(Paginator): + def __init__(self, queryset, page_size, orphans=0, allow_empty_first_page=True): + super(CustomPaginator, self).__init__( + queryset, + page_size, + orphans=2, + allow_empty_first_page=allow_empty_first_page) +class AuthorListCustomPaginator(AuthorList): + paginate_by = 5; + + def get_paginator(self, queryset, page_size, orphans=0, allow_empty_first_page=True): + return super(AuthorListCustomPaginator, self).get_paginator( + queryset, + page_size, + orphans=2, + allow_empty_first_page=allow_empty_first_page) + class ArtistCreate(generic.CreateView): model = Artist -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-upda...@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.