Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #11195 -- Added CSS classes to the changelist cells to allow st…

…yle customizations. Thanks to akaihola, Ramiro Morales and vdboor for their work on the patch.
  • Loading branch information...
commit 4e0ff351466fc2d74cc8d1d40ea78da2b3859d0d 1 parent 47c7553
@jphalip jphalip authored
View
9 django/contrib/admin/templatetags/admin_list.py
@@ -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]
View
3  docs/releases/1.7.txt
@@ -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
=====================================
View
6 tests/admin_changelist/tests.py
@@ -91,7 +91,7 @@ def test_result_list_empty_changelist_value(self):
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 @@ def test_result_list_html(self):
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 @@ def test_result_list_editable_html(self):
# 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):
"""
View
26 tests/admin_views/tests.py
@@ -1496,7 +1496,7 @@ def test_changelist_to_changeform_link(self):
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 @@ def test_pk_hidden_fields(self):
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 @@ def test_pk_hidden_fields_with_list_display_links(self):
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 @@ def testAppModelInDeleteSelectedConfirmationBodyClass(self):
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:
Please sign in to comment.
Something went wrong with that request. Please try again.