Ticket #14206: 14206_r16337.diff

File 14206_r16337.diff, 11.5 KB (added by cyrus, 4 years ago)
  • docs/ref/contrib/admin/index.txt

     
    967967    a ``dictionary``, as described above in the :attr:`ModelAdmin.prepopulated_fields`
    968968    section.
    969969
     970.. method:: ModelAdmin.get_list_display(self, request)
     971
     972    .. versionadded:: 1.4
     973
     974    The ``get_list_display`` method is given the ``HttpRequest`` and is
     975    expected to return a ``list`` or ``tuple`` of field names that will be
     976    displayed on the changelist view as described above in the
     977    :attr:`ModelAdmin.list_display` section.
     978
    970979.. method:: ModelAdmin.get_urls(self)
    971980
    972981    The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
  • django/contrib/admin/options.py

     
    625625            description = capfirst(action.replace('_', ' '))
    626626        return func, action, description
    627627
     628    def get_list_display(self, request):
     629        """
     630        Return a sequence containing the fields to be displayed on the
     631        changelist.
     632        """
     633        return self.list_display
     634
    628635    def construct_change_message(self, request, form, formsets):
    629636        """
    630637        Construct a change message from a changed object.
     
    10531060        actions = self.get_actions(request)
    10541061
    10551062        # Remove action checkboxes if there aren't any actions available.
    1056         list_display = list(self.list_display)
     1063        list_display = list(self.get_list_display(request))
    10571064        if not actions:
    10581065            try:
    10591066                list_display.remove('action_checkbox')
  • tests/regressiontests/admin_changelist/tests.py

     
    44from django.core.paginator import Paginator
    55from django.template import Context, Template
    66from django.test import TransactionTestCase
     7from django.test.client import RequestFactory
     8from django.contrib.auth.models import User
    79
    810from models import (Child, Parent, Genre, Band, Musician, Group, Quartet,
    911    Membership, ChordsMusician, ChordsBand, Invitation)
    1012
    1113
    1214class ChangeListTests(TransactionTestCase):
     15    def setUp(self):
     16        self.factory = RequestFactory()
     17
    1318    def test_select_related_preserved(self):
    1419        """
    1520        Regression test for #10348: ChangeList.get_query_set() shouldn't
    1621        overwrite a custom select_related provided by ModelAdmin.queryset().
    1722        """
    1823        m = ChildAdmin(Child, admin.site)
    19         cl = ChangeList(MockRequest(), Child, m.list_display, m.list_display_links,
     24        request = self.factory.get('/child/')
     25        cl = ChangeList(request, Child, m.list_display, m.list_display_links,
    2026                m.list_filter, m.date_hierarchy, m.search_fields,
    2127                m.list_select_related, m.list_per_page, m.list_editable, m)
    2228        self.assertEqual(cl.query_set.query.select_related, {'parent': {'name': {}}})
     
    2733        for relationship fields
    2834        """
    2935        new_child = Child.objects.create(name='name', parent=None)
    30         request = MockRequest()
     36        request = self.factory.get('/child/')
    3137        m = ChildAdmin(Child, admin.site)
    3238        cl = ChangeList(request, Child, m.list_display, m.list_display_links,
    3339                m.list_filter, m.date_hierarchy, m.search_fields,
     
    4046        self.assertFalse(table_output.find(row_html) == -1,
    4147            'Failed to find expected row element: %s' % table_output)
    4248
    43 
    4449    def test_result_list_html(self):
    4550        """
    4651        Verifies that inclusion tag result_list generates a table when with
     
    4853        """
    4954        new_parent = Parent.objects.create(name='parent')
    5055        new_child = Child.objects.create(name='name', parent=new_parent)
    51         request = MockRequest()
     56        request = self.factory.get('/child/')
    5257        m = ChildAdmin(Child, admin.site)
    5358        cl = ChangeList(request, Child, m.list_display, m.list_display_links,
    5459                m.list_filter, m.date_hierarchy, m.search_fields,
     
    7277        """
    7378        new_parent = Parent.objects.create(name='parent')
    7479        new_child = Child.objects.create(name='name', parent=new_parent)
    75         request = MockRequest()
     80        request = self.factory.get('/child/')
    7681        m = ChildAdmin(Child, admin.site)
    7782
    7883        # Test with list_editable fields
     
    104109        new_parent = Parent.objects.create(name='parent')
    105110        for i in range(200):
    106111            new_child = Child.objects.create(name='name %s' % i, parent=new_parent)
    107         request = MockRequest()
    108         request.GET['p'] = -1 # Anything outside range
     112        request = self.factory.get('/child/', data={'p': -1})  # Anything outside range
    109113        m = ChildAdmin(Child, admin.site)
    110114
    111115        # Test with list_editable fields
     
    122126        for i in range(200):
    123127            new_child = Child.objects.create(name='name %s' % i, parent=new_parent)
    124128
    125         request = MockRequest()
     129        request = self.factory.get('/child/')
    126130        m = ChildAdmin(Child, admin.site)
    127131        m.list_display = ['id', 'name', 'parent']
    128132        m.list_display_links = ['id']
     
    148152        band.genres.add(blues)
    149153
    150154        m = BandAdmin(Band, admin.site)
    151         request = MockFilterRequest('genres', blues.pk)
     155        request = self.factory.get('/band/', data={'genres': blues.pk})
    152156
    153157        cl = ChangeList(request, Band, m.list_display,
    154158                m.list_display_links, m.list_filter, m.date_hierarchy,
     
    171175        Membership.objects.create(group=band, music=lead, role='bass player')
    172176
    173177        m = GroupAdmin(Group, admin.site)
    174         request = MockFilterRequest('members', lead.pk)
     178        request = self.factory.get('/group/', data={'members': lead.pk})
    175179
    176180        cl = ChangeList(request, Group, m.list_display,
    177181                m.list_display_links, m.list_filter, m.date_hierarchy,
     
    195199        Membership.objects.create(group=four, music=lead, role='guitar player')
    196200
    197201        m = QuartetAdmin(Quartet, admin.site)
    198         request = MockFilterRequest('members', lead.pk)
     202        request = self.factory.get('/quartet/', data={'members': lead.pk})
    199203
    200204        cl = ChangeList(request, Quartet, m.list_display,
    201205                m.list_display_links, m.list_filter, m.date_hierarchy,
     
    219223        Invitation.objects.create(band=three, player=lead, instrument='bass')
    220224
    221225        m = ChordsBandAdmin(ChordsBand, admin.site)
    222         request = MockFilterRequest('members', lead.pk)
     226        request = self.factory.get('/chordsband/', data={'members': lead.pk})
    223227
    224228        cl = ChangeList(request, ChordsBand, m.list_display,
    225229                m.list_display_links, m.list_filter, m.date_hierarchy,
     
    242246        Child.objects.create(parent=parent, name='Daniel')
    243247
    244248        m = ParentAdmin(Parent, admin.site)
    245         request = MockFilterRequest('child__name', 'Daniel')
     249        request = self.factory.get('/parent/', data={'child__name': 'Daniel'})
    246250
    247251        cl = ChangeList(request, Parent, m.list_display, m.list_display_links,
    248252                        m.list_filter, m.date_hierarchy, m.search_fields,
     
    262266        Child.objects.create(parent=parent, name='Daniel')
    263267
    264268        m = ParentAdmin(Parent, admin.site)
    265         request = MockSearchRequest('daniel')
     269        request = self.factory.get('/parent/', data={SEARCH_VAR: 'daniel'})
    266270
    267271        cl = ChangeList(request, Parent, m.list_display, m.list_display_links,
    268272                        m.list_filter, m.date_hierarchy, m.search_fields,
     
    282286            Child.objects.create(name='name %s' % i, parent=parent)
    283287            Child.objects.create(name='filtered %s' % i, parent=parent)
    284288
    285         request = MockRequest()
     289        request = self.factory.get('/child/')
    286290
    287291        # Test default queryset
    288292        m = ChildAdmin(Child, admin.site)
     
    302306        self.assertEqual(cl.paginator.count, 30)
    303307        self.assertEqual(cl.paginator.page_range, [1, 2, 3])
    304308
     309    def test_dynamic_list_display(self):
     310        """
     311        Regression tests for #14206: dynamic list_display support.
     312        """
     313        parent = Parent.objects.create(name='parent')
     314        for i in range(10):
     315            Child.objects.create(name='child %s' % i, parent=parent)
    305316
     317        user_noparents = User.objects.create(
     318            username='noparents',
     319            is_superuser=True)
     320        user_parents = User.objects.create(
     321            username='parents',
     322            is_superuser=True)
     323
     324        def _mocked_authenticated_request(user):
     325            request = self.factory.get('/child/')
     326            request.user = user
     327            return request
     328
     329        # Test with user 'noparents'
     330        m = DynamicListDisplayChildAdmin(Child, admin.site)
     331        request = _mocked_authenticated_request(user_noparents)
     332        response = m.changelist_view(request)
     333        # XXX - Calling render here to avoid ContentNotRenderedError to be
     334        # raised. Ticket #15826 should fix this but it's not yet integrated.
     335        response.render()
     336        self.assertNotContains(response, 'Parent object')
     337
     338        # Test with user 'parents'
     339        m = DynamicListDisplayChildAdmin(Child, admin.site)
     340        request = _mocked_authenticated_request(user_parents)
     341        response = m.changelist_view(request)
     342        # XXX - #15826
     343        response.render()
     344        self.assertContains(response, 'Parent object')
     345
     346        # Test default implementation
     347        m = ChildAdmin(Child, admin.site)
     348        request = _mocked_authenticated_request(user_noparents)
     349        response = m.changelist_view(request)
     350        # XXX - #15826
     351        response.render()
     352        self.assertContains(response, 'Parent object')
     353
     354
    306355class ParentAdmin(admin.ModelAdmin):
    307356    list_filter = ['child__name']
    308357    search_fields = ['child__name']
     
    311360class ChildAdmin(admin.ModelAdmin):
    312361    list_display = ['name', 'parent']
    313362    list_per_page = 10
     363
    314364    def queryset(self, request):
    315365        return super(ChildAdmin, self).queryset(request).select_related("parent__name")
    316366
     367
    317368class FilteredChildAdmin(admin.ModelAdmin):
    318369    list_display = ['name', 'parent']
    319370    list_per_page = 10
     371
    320372    def queryset(self, request):
    321373        return super(FilteredChildAdmin, self).queryset(request).filter(
    322374            name__contains='filtered')
    323375
    324 class MockRequest(object):
    325     GET = {}
    326376
    327377class CustomPaginator(Paginator):
    328378    def __init__(self, queryset, page_size, orphans=0, allow_empty_first_page=True):
     
    333383class BandAdmin(admin.ModelAdmin):
    334384    list_filter = ['genres']
    335385
     386
    336387class GroupAdmin(admin.ModelAdmin):
    337388    list_filter = ['members']
    338389
     390
    339391class QuartetAdmin(admin.ModelAdmin):
    340392    list_filter = ['members']
    341393
     394
    342395class ChordsBandAdmin(admin.ModelAdmin):
    343396    list_filter = ['members']
    344397
    345 class MockFilterRequest(object):
    346     def __init__(self, filter, q):
    347         self.GET = {filter: q}
    348398
    349 class MockSearchRequest(object):
    350     def __init__(self, q):
    351         self.GET = {SEARCH_VAR: q}
     399class DynamicListDisplayChildAdmin(admin.ModelAdmin):
     400    list_display = ('name', 'parent')
     401
     402    def get_list_display(self, request):
     403        my_list_display = list(self.list_display)
     404        if request.user.username == 'noparents':
     405            my_list_display.remove('parent')
     406
     407        return my_list_display
Back to Top