Commit ee48da24 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #14773 -- Modified MultipleObjectMixin to allow for custom paginators....

Fixed #14773 -- Modified MultipleObjectMixin to allow for custom paginators. Thanks to piquadrat for the report and initial patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14828 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 23a19240
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ class MultipleObjectMixin(object):
    model = None
    paginate_by = None
    context_object_name = None
    paginator_class = Paginator

    def get_queryset(self):
        """
@@ -32,7 +33,7 @@ class MultipleObjectMixin(object):
        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 @@ class MultipleObjectMixin(object):
        """
        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``
+13 −0
Original line number Diff line number Diff line
@@ -305,6 +305,14 @@ MultipleObjectMixin
        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 @@ MultipleObjectMixin
        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
+16 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ from django.core.exceptions import ImproperlyConfigured
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']
@@ -86,6 +86,21 @@ class ListViewTests(TestCase):
        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)
+4 −0
Original line number Diff line number Diff line
@@ -117,6 +117,10 @@ urlpatterns = patterns('',
        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
+18 −0
Original line number Diff line number Diff line
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,6 +51,23 @@ class AuthorList(generic.ListView):
    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