Ticket #16257: 16257.get_list_display_links.diff

File 16257.get_list_display_links.diff, 10.3 KB (added by julien, 4 years ago)
  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index f052fe1..163110b 100644
    a b class ModelAdmin(BaseModelAdmin): 
    306306        for inline_class in self.inlines:
    307307            inline_instance = inline_class(self.model, self.admin_site)
    308308            self.inline_instances.append(inline_instance)
    309         if 'action_checkbox' not in self.list_display and self.actions is not None:
    310             self.list_display = ['action_checkbox'] +  list(self.list_display)
    311         if not self.list_display_links:
    312             for name in self.list_display:
    313                 if name != 'action_checkbox':
    314                     self.list_display_links = [name]
    315                     break
    316309        super(ModelAdmin, self).__init__()
    317310
    318311    def get_urls(self):
    class ModelAdmin(BaseModelAdmin): 
    637630        Return a sequence containing the fields to be displayed on the
    638631        changelist.
    639632        """
    640         return self.list_display
     633        list_display = self.list_display
     634        if 'action_checkbox' not in list_display and self.actions is not None:
     635            list_display = ['action_checkbox'] +  list(list_display)
     636        return list_display
     637
     638    def get_list_display_links(self, request, list_display):
     639        """
     640        Return a sequence containing the fields to be displayed as links
     641        on the changelist.
     642        """
     643        list_display_links = self.list_display_links
     644        if not list_display_links:
     645            for name in list_display:
     646                if name != 'action_checkbox':
     647                    list_display_links = [name]
     648                    break
     649        return list_display_links
    641650
    642651    def construct_change_message(self, request, form, formsets):
    643652        """
    class ModelAdmin(BaseModelAdmin): 
    10741083            except ValueError:
    10751084                pass
    10761085
     1086        list_display_links = list(self.get_list_display_links(request, list_display))
     1087
    10771088        ChangeList = self.get_changelist(request)
    10781089        try:
    1079             cl = ChangeList(request, self.model, list_display, self.list_display_links,
     1090            cl = ChangeList(request, self.model, list_display, list_display_links,
    10801091                self.list_filter, self.date_hierarchy, self.search_fields,
    10811092                self.list_select_related, self.list_per_page, self.list_editable, self)
    10821093        except IncorrectLookupParameters:
  • docs/ref/contrib/admin/index.txt

    diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
    index c0ff3c6..a640950 100644
    a b templates used by the :class:`ModelAdmin` views: 
    10051005    displayed on the changelist view as described above in the
    10061006    :attr:`ModelAdmin.list_display` section.
    10071007
     1008.. method:: ModelAdmin.get_list_display_links(self, request, list_display)
     1009
     1010    .. versionadded:: 1.4
     1011
     1012    The ``get_list_display_links`` method is given the ``HttpRequest`` and
     1013    the ``list`` or ``tuple`` returned from :meth:`ModelAdmin.get_list_display`
     1014    and is expected to return a ``list`` or ``tuple`` of field names that
     1015    will be displayed on the changelist view as described above in the
     1016    :attr:`ModelAdmin.list_display_links` section.
     1017
    10081018.. method:: ModelAdmin.get_urls(self)
    10091019
    10101020    The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
  • docs/releases/1.4.txt

    diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt
    index cc20795..dbcc292 100644
    a b to work similarly to how desktop GUIs do it. The new hook 
    8080:meth:`~django.contrib.admin.ModelAdmin.get_ordering` for specifying the
    8181ordering dynamically (e.g. depending on the request) has also been added.
    8282
     83New ``ModelAdmin`` methods
     84~~~~~~~~~~~~~~~~~~~~~~~~~~
     85
     86Two new methods, :meth:`~ModelAdmin.get_list_display` and
     87:meth:`~ModelAdmin.get_list_display_links` were added to :class:`~ModelAdmin` to
     88enable the dynamic customization of fields and links to display on the admin
     89change list.
     90
    8391Tools for cryptographic signing
    8492~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    8593
  • tests/regressiontests/admin_changelist/models.py

    diff --git a/tests/regressiontests/admin_changelist/models.py b/tests/regressiontests/admin_changelist/models.py
    index 509d37c..633d8bb 100644
    a b class Parent(models.Model): 
    66class Child(models.Model):
    77    parent = models.ForeignKey(Parent, editable=False, null=True)
    88    name = models.CharField(max_length=30, blank=True)
     9    age = models.IntegerField(null=True, blank=True)
    910
    1011class Genre(models.Model):
    1112    name = models.CharField(max_length=20)
  • tests/regressiontests/admin_changelist/tests.py

    diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py
    index 709fa76..b221990 100644
    a b class ChangeListTests(TestCase): 
    3535        new_child = Child.objects.create(name='name', parent=None)
    3636        request = self.factory.get('/child/')
    3737        m = ChildAdmin(Child, admin.site)
    38         cl = ChangeList(request, Child, m.list_display, m.list_display_links,
     38        list_display = m.get_list_display(request)
     39        list_display_links = m.get_list_display_links(request, list_display)
     40        cl = ChangeList(request, Child, list_display, list_display_links,
    3941                m.list_filter, m.date_hierarchy, m.search_fields,
    4042                m.list_select_related, m.list_per_page, m.list_editable, m)
    4143        cl.formset = None
    class ChangeListTests(TestCase): 
    5557        new_child = Child.objects.create(name='name', parent=new_parent)
    5658        request = self.factory.get('/child/')
    5759        m = ChildAdmin(Child, admin.site)
    58         cl = ChangeList(request, Child, m.list_display, m.list_display_links,
     60        list_display = m.get_list_display(request)
     61        list_display_links = m.get_list_display_links(request, list_display)
     62        cl = ChangeList(request, Child, list_display, list_display_links,
    5963                m.list_filter, m.date_hierarchy, m.search_fields,
    6064                m.list_select_related, m.list_per_page, m.list_editable, m)
    6165        cl.formset = None
    class ChangeListTests(TestCase): 
    335339        response.render()
    336340        self.assertNotContains(response, 'Parent object')
    337341
     342        list_display = m.get_list_display(request)
     343        list_display_links = m.get_list_display_links(request, list_display)
     344        self.assertEqual(list_display, ['action_checkbox', 'name', 'age'])
     345        self.assertEqual(list_display_links, ['name'])
     346
    338347        # Test with user 'parents'
    339348        m = DynamicListDisplayChildAdmin(Child, admin.site)
    340349        request = _mocked_authenticated_request(user_parents)
    class ChangeListTests(TestCase): 
    343352        response.render()
    344353        self.assertContains(response, 'Parent object')
    345354
     355        list_display = m.get_list_display(request)
     356        list_display_links = m.get_list_display_links(request, list_display)
     357        self.assertEqual(list_display, ['action_checkbox', 'parent', 'name', 'age'])
     358        self.assertEqual(list_display_links, ['parent'])
     359
    346360        # Test default implementation
    347361        m = ChildAdmin(Child, admin.site)
    348362        request = _mocked_authenticated_request(user_noparents)
    class ChangeListTests(TestCase): 
    351365        response.render()
    352366        self.assertContains(response, 'Parent object')
    353367
     368    def test_dynamic_list_display_links(self):
     369        """
     370        Regression tests for #16257: dynamic list_display_links support.
     371        """
     372        parent = Parent.objects.create(name='parent')
     373        for i in range(1, 10):
     374            Child.objects.create(id=i, name='child %s' % i, parent=parent, age=i)
     375
     376        superuser = User.objects.create(
     377            username='superuser',
     378            is_superuser=True)
     379
     380        def _mocked_authenticated_request(user):
     381            request = self.factory.get('/child/')
     382            request.user = user
     383            return request
     384
     385        m = DynamicListDisplayLinksChildAdmin(Child, admin.site)
     386        request = _mocked_authenticated_request(superuser)
     387        response = m.changelist_view(request)
     388        # XXX - Calling render here to avoid ContentNotRenderedError to be
     389        # raised. Ticket #15826 should fix this but it's not yet integrated.
     390        response.render()
     391        for i in range(1, 10):
     392            self.assertContains(response, '<a href="%s/">%s</a>' % (i, i))
     393
     394        list_display = m.get_list_display(request)
     395        list_display_links = m.get_list_display_links(request, list_display)
     396        self.assertEqual(list_display, ['action_checkbox', 'parent', 'name', 'age'])
     397        self.assertEqual(list_display_links, ['age'])
     398
    354399
    355400class ParentAdmin(admin.ModelAdmin):
    356401    list_filter = ['child__name']
    class ChordsBandAdmin(admin.ModelAdmin): 
    397442
    398443
    399444class DynamicListDisplayChildAdmin(admin.ModelAdmin):
    400     list_display = ('name', 'parent')
     445    list_display = ('parent', 'name', 'age')
    401446
    402447    def get_list_display(self, request):
    403         my_list_display = list(self.list_display)
     448        my_list_display = super(DynamicListDisplayChildAdmin, self).get_list_display(request)
    404449        if request.user.username == 'noparents':
    405450            my_list_display.remove('parent')
    406 
    407451        return my_list_display
     452
     453class DynamicListDisplayLinksChildAdmin(admin.ModelAdmin):
     454    list_display = ('parent', 'name', 'age')
     455    list_display_links = ['parent', 'name']
     456
     457    def get_list_display_links(self, request, list_display):
     458        return ['age']
  • tests/regressiontests/admin_registration/tests.py

    diff --git a/tests/regressiontests/admin_registration/tests.py b/tests/regressiontests/admin_registration/tests.py
    index 92e9d8a..b92913d 100644
    a b class TestRegistration(TestCase): 
    3939                           search_fields=["name"], list_display=['__str__'])
    4040        self.assertEqual(self.site._registry[Person].search_fields, ['name'])
    4141        self.assertEqual(self.site._registry[Person].list_display,
    42                          ['action_checkbox', '__str__'])
     42                         ['__str__'])
    4343        self.assertTrue(self.site._registry[Person].save_on_top)
    4444
    4545    def test_iterable_registration(self):
Back to Top