Loading django/views/generic/list.py +16 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ class MultipleObjectMixin(ContextMixin): queryset = None model = None paginate_by = None paginate_orphans = 0 context_object_name = None paginator_class = Paginator page_kwarg = 'page' Loading @@ -39,7 +40,9 @@ class MultipleObjectMixin(ContextMixin): """ Paginate the queryset, if needed. """ paginator = self.get_paginator(queryset, page_size, allow_empty_first_page=self.get_allow_empty()) paginator = self.get_paginator( queryset, page_size, orphans=self.get_paginate_orphans(), allow_empty_first_page=self.get_allow_empty()) page_kwarg = self.page_kwarg page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1 try: Loading @@ -64,11 +67,21 @@ class MultipleObjectMixin(ContextMixin): """ return self.paginate_by def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True): def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs): """ 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) return self.paginator_class( queryset, per_page, orphans=orphans, allow_empty_first_page=allow_empty_first_page, **kwargs) def get_paginate_orphans(self): """ Returns the maximum number of orphans extend the last page by when paginating. """ return self.paginate_orphans def get_allow_empty(self): """ Loading docs/ref/class-based-views/flattened-index.txt +7 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,7 @@ ListView * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -290,6 +291,7 @@ ArchiveIndexView * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -325,6 +327,7 @@ YearArchiveView * :attr:`~django.views.generic.dates.BaseYearArchiveView.make_object_list` [:meth:`~django.views.generic.dates.BaseYearArchiveView.get_make_object_list`] * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -363,6 +366,7 @@ MonthArchiveView * :attr:`~django.views.generic.dates.MonthMixin.month` [:meth:`~django.views.generic.dates.MonthMixin.get_month`] * :attr:`~django.views.generic.dates.MonthMixin.month_format` [:meth:`~django.views.generic.dates.MonthMixin.get_month_format`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -401,6 +405,7 @@ WeekArchiveView * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -443,6 +448,7 @@ DayArchiveView * :attr:`~django.views.generic.dates.MonthMixin.month` [:meth:`~django.views.generic.dates.MonthMixin.get_month`] * :attr:`~django.views.generic.dates.MonthMixin.month_format` [:meth:`~django.views.generic.dates.MonthMixin.get_month_format`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -487,6 +493,7 @@ TodayArchiveView * :attr:`~django.views.generic.dates.MonthMixin.month` [:meth:`~django.views.generic.dates.MonthMixin.get_month`] * :attr:`~django.views.generic.dates.MonthMixin.month_format` [:meth:`~django.views.generic.dates.MonthMixin.get_month_format`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading docs/ref/class-based-views/mixins-multiple-object.txt +18 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,16 @@ MultipleObjectMixin expect either a ``page`` query string parameter (via ``request.GET``) or a ``page`` variable specified in the URLconf. .. attribute:: paginate_orphans .. versionadded:: 1.6 An integer specifying the number of "overflow" objects the last page can contain. This extends the :attr:`MultipleObjectMixin.paginate_by` limit on the last page by up to :attr:`MultipleObjectMixin.paginate_orphans`, in order to keep the last page from having a very small number of objects. .. attribute:: page_kwarg .. versionadded:: 1.5 Loading Loading @@ -119,6 +129,14 @@ MultipleObjectMixin Returns an instance of the paginator to use for this view. By default, instantiates an instance of :attr:`paginator_class`. .. method:: get_paginate_by() .. versionadded:: 1.6 An integer specifying the number of "overflow" objects the last page can contain. By default this simply returns the value of :attr:`MultipleObjectMixin.paginate_orphans`. .. method:: get_allow_empty() Return a boolean specifying whether to display the page if no objects Loading tests/regressiontests/generic_views/list.py +18 −0 Original line number Diff line number Diff line Loading @@ -118,8 +118,26 @@ class ListViewTests(TestCase): # Custom pagination allows for 2 orphans on a page size of 5 self.assertEqual(len(res.context['object_list']), 7) def test_paginated_orphaned_queryset(self): self._make_authors(92) res = self.client.get('/list/authors/paginated-orphaned/') self.assertEqual(res.status_code, 200) self.assertEqual(res.context['page_obj'].number, 1) res = self.client.get( '/list/authors/paginated-orphaned/', {'page': 'last'}) self.assertEqual(res.status_code, 200) self.assertEqual(res.context['page_obj'].number, 3) res = self.client.get( '/list/authors/paginated-orphaned/', {'page': '3'}) self.assertEqual(res.status_code, 200) self.assertEqual(res.context['page_obj'].number, 3) res = self.client.get( '/list/authors/paginated-orphaned/', {'page': '4'}) self.assertEqual(res.status_code, 404) def test_paginated_non_queryset(self): res = self.client.get('/list/dict/paginated/') self.assertEqual(res.status_code, 200) self.assertEqual(len(res.context['object_list']), 1) Loading tests/regressiontests/generic_views/urls.py +2 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,8 @@ urlpatterns = patterns('', views.AuthorList.as_view(paginate_by=30)), (r'^list/authors/paginated/(?P<page>\d+)/$', views.AuthorList.as_view(paginate_by=30)), (r'^list/authors/paginated-orphaned/$', views.AuthorList.as_view(paginate_by=30, paginate_orphans=2)), (r'^list/authors/notempty/$', views.AuthorList.as_view(allow_empty=False)), (r'^list/authors/notempty/paginated/$', Loading Loading
django/views/generic/list.py +16 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ class MultipleObjectMixin(ContextMixin): queryset = None model = None paginate_by = None paginate_orphans = 0 context_object_name = None paginator_class = Paginator page_kwarg = 'page' Loading @@ -39,7 +40,9 @@ class MultipleObjectMixin(ContextMixin): """ Paginate the queryset, if needed. """ paginator = self.get_paginator(queryset, page_size, allow_empty_first_page=self.get_allow_empty()) paginator = self.get_paginator( queryset, page_size, orphans=self.get_paginate_orphans(), allow_empty_first_page=self.get_allow_empty()) page_kwarg = self.page_kwarg page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1 try: Loading @@ -64,11 +67,21 @@ class MultipleObjectMixin(ContextMixin): """ return self.paginate_by def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True): def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs): """ 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) return self.paginator_class( queryset, per_page, orphans=orphans, allow_empty_first_page=allow_empty_first_page, **kwargs) def get_paginate_orphans(self): """ Returns the maximum number of orphans extend the last page by when paginating. """ return self.paginate_orphans def get_allow_empty(self): """ Loading
docs/ref/class-based-views/flattened-index.txt +7 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,7 @@ ListView * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -290,6 +291,7 @@ ArchiveIndexView * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -325,6 +327,7 @@ YearArchiveView * :attr:`~django.views.generic.dates.BaseYearArchiveView.make_object_list` [:meth:`~django.views.generic.dates.BaseYearArchiveView.get_make_object_list`] * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -363,6 +366,7 @@ MonthArchiveView * :attr:`~django.views.generic.dates.MonthMixin.month` [:meth:`~django.views.generic.dates.MonthMixin.get_month`] * :attr:`~django.views.generic.dates.MonthMixin.month_format` [:meth:`~django.views.generic.dates.MonthMixin.get_month_format`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -401,6 +405,7 @@ WeekArchiveView * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.list.MultipleObjectMixin.model` * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -443,6 +448,7 @@ DayArchiveView * :attr:`~django.views.generic.dates.MonthMixin.month` [:meth:`~django.views.generic.dates.MonthMixin.get_month`] * :attr:`~django.views.generic.dates.MonthMixin.month_format` [:meth:`~django.views.generic.dates.MonthMixin.get_month_format`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading Loading @@ -487,6 +493,7 @@ TodayArchiveView * :attr:`~django.views.generic.dates.MonthMixin.month` [:meth:`~django.views.generic.dates.MonthMixin.get_month`] * :attr:`~django.views.generic.dates.MonthMixin.month_format` [:meth:`~django.views.generic.dates.MonthMixin.get_month_format`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_by`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_orphans` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_paginate_orphans`] * :attr:`~django.views.generic.list.MultipleObjectMixin.paginator_class` * :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`] * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` Loading
docs/ref/class-based-views/mixins-multiple-object.txt +18 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,16 @@ MultipleObjectMixin expect either a ``page`` query string parameter (via ``request.GET``) or a ``page`` variable specified in the URLconf. .. attribute:: paginate_orphans .. versionadded:: 1.6 An integer specifying the number of "overflow" objects the last page can contain. This extends the :attr:`MultipleObjectMixin.paginate_by` limit on the last page by up to :attr:`MultipleObjectMixin.paginate_orphans`, in order to keep the last page from having a very small number of objects. .. attribute:: page_kwarg .. versionadded:: 1.5 Loading Loading @@ -119,6 +129,14 @@ MultipleObjectMixin Returns an instance of the paginator to use for this view. By default, instantiates an instance of :attr:`paginator_class`. .. method:: get_paginate_by() .. versionadded:: 1.6 An integer specifying the number of "overflow" objects the last page can contain. By default this simply returns the value of :attr:`MultipleObjectMixin.paginate_orphans`. .. method:: get_allow_empty() Return a boolean specifying whether to display the page if no objects Loading
tests/regressiontests/generic_views/list.py +18 −0 Original line number Diff line number Diff line Loading @@ -118,8 +118,26 @@ class ListViewTests(TestCase): # Custom pagination allows for 2 orphans on a page size of 5 self.assertEqual(len(res.context['object_list']), 7) def test_paginated_orphaned_queryset(self): self._make_authors(92) res = self.client.get('/list/authors/paginated-orphaned/') self.assertEqual(res.status_code, 200) self.assertEqual(res.context['page_obj'].number, 1) res = self.client.get( '/list/authors/paginated-orphaned/', {'page': 'last'}) self.assertEqual(res.status_code, 200) self.assertEqual(res.context['page_obj'].number, 3) res = self.client.get( '/list/authors/paginated-orphaned/', {'page': '3'}) self.assertEqual(res.status_code, 200) self.assertEqual(res.context['page_obj'].number, 3) res = self.client.get( '/list/authors/paginated-orphaned/', {'page': '4'}) self.assertEqual(res.status_code, 404) def test_paginated_non_queryset(self): res = self.client.get('/list/dict/paginated/') self.assertEqual(res.status_code, 200) self.assertEqual(len(res.context['object_list']), 1) Loading
tests/regressiontests/generic_views/urls.py +2 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,8 @@ urlpatterns = patterns('', views.AuthorList.as_view(paginate_by=30)), (r'^list/authors/paginated/(?P<page>\d+)/$', views.AuthorList.as_view(paginate_by=30)), (r'^list/authors/paginated-orphaned/$', views.AuthorList.as_view(paginate_by=30, paginate_orphans=2)), (r'^list/authors/notempty/$', views.AuthorList.as_view(allow_empty=False)), (r'^list/authors/notempty/paginated/$', Loading