Ticket #14900: admin-paginator.diff

File admin-paginator.diff, 9.1 KB (added by Adam Vandenberg, 13 years ago)
  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index 7a42e94..bb11b3d 100644
    a b from django.contrib.admin.util import unquote, flatten_fieldsets, get_deleted_ob  
    99from django.contrib import messages
    1010from django.views.decorators.csrf import csrf_protect
    1111from django.core.exceptions import PermissionDenied, ValidationError
     12from django.core.paginator import Paginator
    1213from django.db import models, transaction, router
    1314from django.db.models.fields import BLANK_CHOICE_DASH
    1415from django.http import Http404, HttpResponse, HttpResponseRedirect
    class ModelAdmin(BaseModelAdmin):  
    215216    date_hierarchy = None
    216217    save_as = False
    217218    save_on_top = False
     219    paginator_class = Paginator
    218220    inlines = []
    219221
    220222    # Custom templates (designed to be over-ridden in subclasses)
    class ModelAdmin(BaseModelAdmin):  
    975977
    976978        ChangeList = self.get_changelist(request)
    977979        try:
    978             cl = ChangeList(request, self.model, list_display, self.list_display_links, self.list_filter,
    979                 self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self)
     980            cl = ChangeList(request, self.model, list_display, self.list_display_links,
     981                self.list_filter, self.date_hierarchy, self.search_fields,
     982                self.list_select_related, self.list_per_page, self.list_editable, self.paginator_class, self)
    980983        except IncorrectLookupParameters:
    981984            # Wacky lookup parameters were given, so redirect to the main
    982985            # changelist page, without parameters, and pass an 'invalid=1'
  • django/contrib/admin/views/main.py

    diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
    index 606388c..19c7399 100644
    a b ERROR_FLAG = 'e'  
    2626EMPTY_CHANGELIST_VALUE = '(None)'
    2727
    2828class ChangeList(object):
    29     def __init__(self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, list_select_related, list_per_page, list_editable, model_admin):
     29    def __init__(self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, list_select_related, list_per_page, list_editable, paginator_class, model_admin):
    3030        self.model = model
    3131        self.opts = model._meta
    3232        self.lookup_opts = self.opts
    class ChangeList(object):  
    4040        self.list_per_page = list_per_page
    4141        self.list_editable = list_editable
    4242        self.model_admin = model_admin
     43        self.paginator_class = paginator_class
    4344
    4445        # Get search parameters from the query string.
    4546        try:
    class ChangeList(object):  
    9495        return '?%s' % urlencode(p)
    9596
    9697    def get_results(self, request):
    97         paginator = Paginator(self.query_set, self.list_per_page)
     98        paginator = self.get_paginator(self.query_set, self.list_per_page)
    9899        # Get the number of objects, with admin filters applied.
    99100        result_count = paginator.count
    100101
    class ChangeList(object):  
    244245
    245246    def url_for_result(self, result):
    246247        return "%s/" % quote(getattr(result, self.pk_attname))
     248
     249    def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True):
     250        return self.paginator_class(queryset, per_page, orphans, allow_empty_first_page)
  • docs/ref/contrib/admin/index.txt

    diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
    index 9928118..cb07cb6 100644
    a b subclass::  
    516516        Django will only honor the first element in the list/tuple; any others
    517517        will be ignored.
    518518
     519.. attribute:: ModelAdmin.paginator_class
     520
     521    .. versionadded:: 1.3
     522
     523    The paginator class to be used for pagination. By default,
     524    :class:`django.core.paginator.Paginator` is used. If the custom paginator
     525    class doesn't have the same constructor interface as
     526    :class:`django.core.paginator.Paginator`, you will also need to
     527    provide an implementation for :meth:`MultipleObjectMixin.get_paginator`.
     528
    519529.. attribute:: ModelAdmin.prepopulated_fields
    520530
    521531    Set ``prepopulated_fields`` to a dictionary mapping field names to the
    templates used by the :class:`ModelAdmin` views:  
    945955    using the :mod:`django.contrib.messages` backend. See the
    946956    :ref:`custom ModelAdmin example <custom-admin-action>`.
    947957
     958.. method:: ModelAdmin.get_paginator(queryset, per_page, orphans=0, allow_empty_first_page=True)
     959
     960    .. versionadded:: 1.3
     961
     962    Returns an instance of the paginator to use for this view. By default,
     963    instantiates an instance of :attr:`paginator_class`.
     964
    948965Other methods
    949966~~~~~~~~~~~~~
    950967
  • tests/regressiontests/admin_changelist/tests.py

    diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py
    index 96b36f8..b94a79b 100644
    a b  
    11from django.contrib import admin
    22from django.contrib.admin.options import IncorrectLookupParameters
    33from django.contrib.admin.views.main import ChangeList
     4from django.core.paginator import Paginator
    45from django.template import Context, Template
    56from django.test import TransactionTestCase
     7
    68from regressiontests.admin_changelist.models import Child, Parent
    79
     10
    811class ChangeListTests(TransactionTestCase):
    912    def test_select_related_preserved(self):
    1013        """
    class ChangeListTests(TransactionTestCase):  
    1417        m = ChildAdmin(Child, admin.site)
    1518        cl = ChangeList(MockRequest(), Child, m.list_display, m.list_display_links,
    1619                m.list_filter, m.date_hierarchy, m.search_fields,
    17                 m.list_select_related, m.list_per_page, m.list_editable, m)
     20                m.list_select_related, m.list_per_page, m.list_editable,
     21                m.paginator_class, m)
    1822        self.assertEqual(cl.query_set.query.select_related, {'parent': {'name': {}}})
    1923
    2024    def test_result_list_html(self):
    class ChangeListTests(TransactionTestCase):  
    2832        m = ChildAdmin(Child, admin.site)
    2933        cl = ChangeList(request, Child, m.list_display, m.list_display_links,
    3034                m.list_filter, m.date_hierarchy, m.search_fields,
    31                 m.list_select_related, m.list_per_page, m.list_editable, m)
     35                m.list_select_related, m.list_per_page, m.list_editable,
     36                m.paginator_class, m)
    3237        cl.formset = None
    3338        template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
    3439        context = Context({'cl': cl})
    class ChangeListTests(TransactionTestCase):  
    5762        m.list_editable = ['name']
    5863        cl = ChangeList(request, Child, m.list_display, m.list_display_links,
    5964                m.list_filter, m.date_hierarchy, m.search_fields,
    60                 m.list_select_related, m.list_per_page, m.list_editable, m)
     65                m.list_select_related, m.list_per_page, m.list_editable,
     66                m.paginator_class, m)
    6167        FormSet = m.get_changelist_formset(request)
    6268        cl.formset = FormSet(queryset=cl.result_list)
    6369        template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
    class ChangeListTests(TransactionTestCase):  
    9197        self.assertRaises(IncorrectLookupParameters, lambda: \
    9298            ChangeList(request, Child, m.list_display, m.list_display_links,
    9399                    m.list_filter, m.date_hierarchy, m.search_fields,
    94                     m.list_select_related, m.list_per_page, m.list_editable, m))
     100                    m.list_select_related, m.list_per_page, m.list_editable,
     101                    m.paginator_class, m))
     102
     103    def test_custom_paginator(self):
     104        new_parent = Parent.objects.create(name='parent')
     105        for i in range(200):
     106            new_child = Child.objects.create(name='name %s' % i, parent=new_parent)
     107
     108        request = MockRequest()
     109        m = ChildAdmin(Child, admin.site)
     110        m.list_display = ['id', 'name', 'parent']
     111        m.list_display_links = ['id']
     112        m.list_editable = ['name']
     113        m.paginator_class = CustomPaginator
     114
     115        cl = ChangeList(request, Child, m.list_display, m.list_display_links,
     116                m.list_filter, m.date_hierarchy, m.search_fields,
     117                m.list_select_related, m.list_per_page, m.list_editable,
     118                m.paginator_class, m)
     119
     120        cl.get_results(request)
     121        self.assertIsInstance(cl.paginator, CustomPaginator)
    95122
    96123
    97124class ChildAdmin(admin.ModelAdmin):
    class ChildAdmin(admin.ModelAdmin):  
    99126    def queryset(self, request):
    100127        return super(ChildAdmin, self).queryset(request).select_related("parent__name")
    101128
     129
    102130class MockRequest(object):
    103131    GET = {}
     132
     133
     134class CustomPaginator(Paginator):
     135    def __init__(self, queryset, page_size, orphans=0, allow_empty_first_page=True):
     136        super(CustomPaginator, self).__init__(
     137            queryset,
     138            5,
     139            orphans=2,
     140            allow_empty_first_page=allow_empty_first_page)
Back to Top