Commit 4e0ff351 authored by Julien Phalip's avatar Julien Phalip
Browse files

Fixed #11195 -- Added CSS classes to the changelist cells to allow style...

Fixed #11195 -- Added CSS classes to the changelist cells to allow style customizations. Thanks to akaihola, Ramiro Morales and vdboor for their work on the patch.
parent 47c75532
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ def items_for_result(cl, result, form):
    first = True
    pk = cl.lookup_opts.pk.attname
    for field_name in cl.list_display:
        row_class = ''
        row_classes = ['field-%s' % field_name]
        try:
            f, attr, value = lookup_field(field_name, result, cl.model_admin)
        except ObjectDoesNotExist:
@@ -188,7 +188,7 @@ def items_for_result(cl, result, form):
        else:
            if f is None:
                if field_name == 'action_checkbox':
                    row_class = mark_safe(' class="action-checkbox"')
                    row_classes = ['action-checkbox']
                allow_tags = getattr(attr, 'allow_tags', False)
                boolean = getattr(attr, 'boolean', False)
                if boolean:
@@ -199,7 +199,7 @@ def items_for_result(cl, result, form):
                if allow_tags:
                    result_repr = mark_safe(result_repr)
                if isinstance(value, (datetime.date, datetime.time)):
                    row_class = mark_safe(' class="nowrap"')
                    row_classes.append('nowrap')
            else:
                if isinstance(f.rel, models.ManyToOneRel):
                    field_val = getattr(result, f.name)
@@ -210,9 +210,10 @@ def items_for_result(cl, result, form):
                else:
                    result_repr = display_for_field(value, f)
                if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
                    row_class = mark_safe(' class="nowrap"')
                    row_classes.append('nowrap')
        if force_text(result_repr) == '':
            result_repr = mark_safe(' ')
        row_class = mark_safe(' class="%s"' % ' '.join(row_classes))
        # If list_display_links not defined, add the link tag to the first field
        if (first and not cl.list_display_links) or field_name in cl.list_display_links:
            table_tag = {True:'th', False:'td'}[first]
+3 −0
Original line number Diff line number Diff line
@@ -82,6 +82,9 @@ Minor features
* Buttons in :mod:`django.contrib.admin` now use the ``border-radius`` CSS
  property for rounded corners rather than GIF background images.

* The admin changelist cells now have a ``field-<field_name>`` class in the
  HTML to enable style customizations.

Backwards incompatible changes in 1.7
=====================================

+3 −3
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ class ChangeListTests(TestCase):
        context = Context({'cl': cl})
        table_output = template.render(context)
        link = reverse('admin:admin_changelist_child_change', args=(new_child.id,))
        row_html = '<tbody><tr class="row1"><th><a href="%s">name</a></th><td class="nowrap">(None)</td></tr></tbody>' % link
        row_html = '<tbody><tr class="row1"><th class="field-name"><a href="%s">name</a></th><td class="field-parent nowrap">(None)</td></tr></tbody>' % link
        self.assertFalse(table_output.find(row_html) == -1,
            'Failed to find expected row element: %s' % table_output)

@@ -114,7 +114,7 @@ class ChangeListTests(TestCase):
        context = Context({'cl': cl})
        table_output = template.render(context)
        link = reverse('admin:admin_changelist_child_change', args=(new_child.id,))
        row_html = '<tbody><tr class="row1"><th><a href="%s">name</a></th><td class="nowrap">Parent object</td></tr></tbody>' % link
        row_html = '<tbody><tr class="row1"><th class="field-name"><a href="%s">name</a></th><td class="field-parent nowrap">Parent object</td></tr></tbody>' % link
        self.assertFalse(table_output.find(row_html) == -1,
            'Failed to find expected row element: %s' % table_output)

@@ -150,7 +150,7 @@ class ChangeListTests(TestCase):

        # make sure that list editable fields are rendered in divs correctly
        editable_name_field = '<input name="form-0-name" value="name" class="vTextField" maxlength="30" type="text" id="id_form-0-name" />'
        self.assertInHTML('<td>%s</td>' % editable_name_field, table_output, msg_prefix='Failed to find "name" list_editable field')
        self.assertInHTML('<td class="field-name">%s</td>' % editable_name_field, table_output, msg_prefix='Failed to find "name" list_editable field')

    def test_result_list_editable(self):
        """
+21 −5
Original line number Diff line number Diff line
@@ -1496,7 +1496,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
        response = self.client.get(prefix)
        # this URL now comes through reverse(), thus url quoting and iri_to_uri encoding
        pk_final_url = escape(iri_to_uri(urlquote(quote(self.pk))))
        should_contain = """<th><a href="%s%s/">%s</a></th>""" % (prefix, pk_final_url, escape(self.pk))
        should_contain = """<th class="field-__str__"><a href="%s%s/">%s</a></th>""" % (prefix, pk_final_url, escape(self.pk))
        self.assertContains(response, should_contain)

    def test_recentactions_link(self):
@@ -2151,8 +2151,8 @@ class AdminViewListEditable(TestCase):
        self.assertContains(response, 'id="id_form-0-id"', 1)  # Only one hidden field, in a separate place than the table.
        self.assertContains(response, 'id="id_form-1-id"', 1)
        self.assertContains(response, '<div class="hiddenfields">\n<input type="hidden" name="form-0-id" value="%d" id="id_form-0-id" /><input type="hidden" name="form-1-id" value="%d" id="id_form-1-id" />\n</div>' % (story2.id, story1.id), html=True)
        self.assertContains(response, '<td>%d</td>' % story1.id, 1)
        self.assertContains(response, '<td>%d</td>' % story2.id, 1)
        self.assertContains(response, '<td class="field-id">%d</td>' % story1.id, 1)
        self.assertContains(response, '<td class="field-id">%d</td>' % story2.id, 1)

    def test_pk_hidden_fields_with_list_display_links(self):
        """ Similarly as test_pk_hidden_fields, but when the hidden pk fields are
@@ -2167,8 +2167,8 @@ class AdminViewListEditable(TestCase):
        self.assertContains(response, 'id="id_form-0-id"', 1)  # Only one hidden field, in a separate place than the table.
        self.assertContains(response, 'id="id_form-1-id"', 1)
        self.assertContains(response, '<div class="hiddenfields">\n<input type="hidden" name="form-0-id" value="%d" id="id_form-0-id" /><input type="hidden" name="form-1-id" value="%d" id="id_form-1-id" />\n</div>' % (story2.id, story1.id), html=True)
        self.assertContains(response, '<th><a href="%s">%d</a></th>' % (link1, story1.id), 1)
        self.assertContains(response, '<th><a href="%s">%d</a></th>' % (link2, story2.id), 1)
        self.assertContains(response, '<th class="field-id"><a href="%s">%d</a></th>' % (link1, story1.id), 1)
        self.assertContains(response, '<th class="field-id"><a href="%s">%d</a></th>' % (link2, story2.id), 1)


@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
@@ -3877,6 +3877,22 @@ class CSSTest(TestCase):
        self.assertContains(response,
            '<body class="app-admin_views model-section ')

    def test_changelist_field_classes(self):
        """
        Cells of the change list table should contain the field name in their class attribute
        Refs #11195.
        """
        Podcast.objects.create(name="Django Dose",
            release_date=datetime.date.today())
        response = self.client.get('/test_admin/admin/admin_views/podcast/')
        self.assertContains(
            response, '<th class="field-name">')
        self.assertContains(
            response, '<td class="field-release_date nowrap">')
        self.assertContains(
            response, '<td class="action-checkbox">')


try:
    import docutils
except ImportError: