diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py index 5f5919d517..0c0b3a4e34 100644 --- a/django/contrib/admin/helpers.py +++ b/django/contrib/admin/helpers.py @@ -279,6 +279,7 @@ class InlineAdminFormSet: continue if not self.has_change_permission or field_name in self.readonly_fields: yield { + 'name': field_name, 'label': meta_labels.get(field_name) or label_for_field(field_name, self.opts.model, self.opts), 'widget': {'is_hidden': False}, 'required': False, @@ -290,6 +291,7 @@ class InlineAdminFormSet: if label is None: label = label_for_field(field_name, self.opts.model, self.opts) yield { + 'name': field_name, 'label': label, 'widget': form_field.widget, 'required': form_field.required, diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html index 2395d1cb6d..531d7b6a21 100644 --- a/django/contrib/admin/templates/admin/edit_inline/tabular.html +++ b/django/contrib/admin/templates/admin/edit_inline/tabular.html @@ -12,7 +12,7 @@ {% for field in inline_admin_formset.fields %} {% if not field.widget.is_hidden %} - {{ field.label|capfirst }} + {{ field.label|capfirst }} {% if field.help_text %} ({{ field.help_text|striptags }}){% endif %} {% endif %} diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt index 01eb2b7d47..c00cb9cd41 100644 --- a/docs/releases/2.2.txt +++ b/docs/releases/2.2.txt @@ -44,7 +44,8 @@ Minor features :mod:`django.contrib.admin` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* ... +* Added a CSS class to the column headers of + :class:`~django.contrib.admin.TabularInline`. :mod:`django.contrib.admindocs` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/admin_inlines/models.py b/tests/admin_inlines/models.py index cb1ec39ae5..38b2999f79 100644 --- a/tests/admin_inlines/models.py +++ b/tests/admin_inlines/models.py @@ -152,6 +152,7 @@ class Poll(models.Model): class Question(models.Model): + text = models.CharField(max_length=40) poll = models.ForeignKey(Poll, models.CASCADE) diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py index 749b3dd75f..66cf57dba1 100644 --- a/tests/admin_inlines/tests.py +++ b/tests/admin_inlines/tests.py @@ -85,13 +85,27 @@ class TestInline(TestDataMixin, TestCase): self.assertEqual(response.status_code, 302) self.assertEqual(len(Fashionista.objects.filter(person__firstname='Imelda')), 1) + def test_tabular_inline_column_css_class(self): + """ + Field names are included in the context to output a field-specific + CSS class name in the column headers. + """ + response = self.client.get(reverse('admin:admin_inlines_poll_add')) + text_field, call_me_field = list(response.context['inline_admin_formset'].fields()) + # Editable field. + self.assertEqual(text_field['name'], 'text') + self.assertContains(response, '') + # Read-only field. + self.assertEqual(call_me_field['name'], 'call_me') + self.assertContains(response, '') + def test_custom_form_tabular_inline_label(self): """ A model form with a form field specified (TitleForm.title1) should have its label rendered in the tabular inline. """ response = self.client.get(reverse('admin:admin_inlines_titlecollection_add')) - self.assertContains(response, 'Title1', html=True) + self.assertContains(response, 'Title1', html=True) def test_custom_form_tabular_inline_overridden_label(self): """ @@ -101,7 +115,7 @@ class TestInline(TestDataMixin, TestCase): response = self.client.get(reverse('admin:admin_inlines_someparentmodel_add')) field = list(response.context['inline_admin_formset'].fields())[0] self.assertEqual(field['label'], 'new label') - self.assertContains(response, 'New label', html=True) + self.assertContains(response, 'New label', html=True) def test_tabular_non_field_errors(self): """ @@ -710,7 +724,7 @@ class TestInlinePermissions(TestCase): html=True ) # TabularInline - self.assertContains(response, 'Dummy', html=True) + self.assertContains(response, 'Dummy', html=True) self.assertContains( response, 'Dummy', html=True) + self.assertContains(response, 'Dummy', html=True) self.assertContains( response, '