mirror of https://github.com/django/django.git
parent
fbfa654a15
commit
48e8b5e944
|
@ -15,6 +15,7 @@ class MultipleObjectMixin(ContextMixin):
|
||||||
queryset = None
|
queryset = None
|
||||||
model = None
|
model = None
|
||||||
paginate_by = None
|
paginate_by = None
|
||||||
|
paginate_orphans = 0
|
||||||
context_object_name = None
|
context_object_name = None
|
||||||
paginator_class = Paginator
|
paginator_class = Paginator
|
||||||
page_kwarg = 'page'
|
page_kwarg = 'page'
|
||||||
|
@ -39,7 +40,9 @@ class MultipleObjectMixin(ContextMixin):
|
||||||
"""
|
"""
|
||||||
Paginate the queryset, if needed.
|
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_kwarg = self.page_kwarg
|
||||||
page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
|
page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
|
||||||
try:
|
try:
|
||||||
|
@ -64,11 +67,21 @@ class MultipleObjectMixin(ContextMixin):
|
||||||
"""
|
"""
|
||||||
return self.paginate_by
|
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 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):
|
def get_allow_empty(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -116,6 +116,7 @@ ListView
|
||||||
* :attr:`~django.views.generic.base.View.http_method_names`
|
* :attr:`~django.views.generic.base.View.http_method_names`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.model`
|
* :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_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.paginator_class`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
||||||
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
||||||
|
@ -290,6 +291,7 @@ ArchiveIndexView
|
||||||
* :attr:`~django.views.generic.base.View.http_method_names`
|
* :attr:`~django.views.generic.base.View.http_method_names`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.model`
|
* :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_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.paginator_class`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
||||||
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
||||||
|
@ -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.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.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_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.paginator_class`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
||||||
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
||||||
|
@ -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` [: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.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_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.paginator_class`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
||||||
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
||||||
|
@ -401,6 +405,7 @@ WeekArchiveView
|
||||||
* :attr:`~django.views.generic.base.View.http_method_names`
|
* :attr:`~django.views.generic.base.View.http_method_names`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.model`
|
* :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_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.paginator_class`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
||||||
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
||||||
|
@ -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` [: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.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_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.paginator_class`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
||||||
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
||||||
|
@ -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` [: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.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_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.paginator_class`
|
||||||
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
* :attr:`~django.views.generic.list.MultipleObjectMixin.queryset` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`]
|
||||||
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
* :attr:`~django.views.generic.base.TemplateResponseMixin.response_class`
|
||||||
|
|
|
@ -72,6 +72,16 @@ MultipleObjectMixin
|
||||||
expect either a ``page`` query string parameter (via ``request.GET``)
|
expect either a ``page`` query string parameter (via ``request.GET``)
|
||||||
or a ``page`` variable specified in the URLconf.
|
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
|
.. attribute:: page_kwarg
|
||||||
|
|
||||||
.. versionadded:: 1.5
|
.. versionadded:: 1.5
|
||||||
|
@ -119,6 +129,14 @@ MultipleObjectMixin
|
||||||
Returns an instance of the paginator to use for this view. By default,
|
Returns an instance of the paginator to use for this view. By default,
|
||||||
instantiates an instance of :attr:`paginator_class`.
|
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()
|
.. method:: get_allow_empty()
|
||||||
|
|
||||||
Return a boolean specifying whether to display the page if no objects
|
Return a boolean specifying whether to display the page if no objects
|
||||||
|
|
|
@ -118,8 +118,26 @@ class ListViewTests(TestCase):
|
||||||
# Custom pagination allows for 2 orphans on a page size of 5
|
# Custom pagination allows for 2 orphans on a page size of 5
|
||||||
self.assertEqual(len(res.context['object_list']), 7)
|
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):
|
def test_paginated_non_queryset(self):
|
||||||
res = self.client.get('/list/dict/paginated/')
|
res = self.client.get('/list/dict/paginated/')
|
||||||
|
|
||||||
self.assertEqual(res.status_code, 200)
|
self.assertEqual(res.status_code, 200)
|
||||||
self.assertEqual(len(res.context['object_list']), 1)
|
self.assertEqual(len(res.context['object_list']), 1)
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,8 @@ urlpatterns = patterns('',
|
||||||
views.AuthorList.as_view(paginate_by=30)),
|
views.AuthorList.as_view(paginate_by=30)),
|
||||||
(r'^list/authors/paginated/(?P<page>\d+)/$',
|
(r'^list/authors/paginated/(?P<page>\d+)/$',
|
||||||
views.AuthorList.as_view(paginate_by=30)),
|
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/$',
|
(r'^list/authors/notempty/$',
|
||||||
views.AuthorList.as_view(allow_empty=False)),
|
views.AuthorList.as_view(allow_empty=False)),
|
||||||
(r'^list/authors/notempty/paginated/$',
|
(r'^list/authors/notempty/paginated/$',
|
||||||
|
|
Loading…
Reference in New Issue