Loading django/forms/forms.py +4 −3 Original line number Diff line number Diff line Loading @@ -525,10 +525,11 @@ class BoundField(object): widget = self.field.widget id_ = widget.attrs.get('id') or self.auto_id if id_: id_for_label = widget.id_for_label(id_) if id_for_label: attrs = dict(attrs or {}, **{'for': id_for_label}) attrs = flatatt(attrs) if attrs else '' contents = format_html('<label for="{0}"{1}>{2}</label>', widget.id_for_label(id_), attrs, contents ) contents = format_html('<label{0}>{1}</label>', attrs, contents) else: contents = conditional_escape(contents) return mark_safe(contents) Loading tests/admin_util/tests.py +11 −12 Original line number Diff line number Diff line Loading @@ -11,8 +11,7 @@ from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE from django.contrib.sites.models import Site from django.db import models, DEFAULT_DB_ALIAS from django import forms from django.test import TestCase from django.utils import unittest from django.test import SimpleTestCase, TestCase from django.utils.formats import localize from django.utils.safestring import mark_safe from django.utils import six Loading Loading @@ -82,7 +81,7 @@ class NestedObjectsTests(TestCase): # One for Location, one for Guest, and no query for EventGuide n.collect(objs) class UtilTests(unittest.TestCase): class UtilTests(SimpleTestCase): def test_values_from_lookup_field(self): """ Regression test for #12654: lookup_field Loading Loading @@ -151,7 +150,7 @@ class UtilTests(unittest.TestCase): # handling. display_value = display_for_field(None, models.NullBooleanField()) expected = '<img src="%sadmin/img/icon-unknown.gif" alt="None" />' % settings.STATIC_URL self.assertEqual(display_value, expected) self.assertHTMLEqual(display_value, expected) display_value = display_for_field(None, models.DecimalField()) self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) Loading Loading @@ -299,9 +298,9 @@ class UtilTests(unittest.TestCase): cb = forms.BooleanField(label=mark_safe('<i>cb</i>')) form = MyForm() self.assertEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), '<label for="id_text" class="required inline"><i>text</i>:</label>') self.assertEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i></label>') # normal strings needs to be escaped Loading @@ -310,9 +309,9 @@ class UtilTests(unittest.TestCase): cb = forms.BooleanField(label='&cb') form = MyForm() self.assertEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), '<label for="id_text" class="required inline">&text:</label>') self.assertEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), '<label for="id_cb" class="vCheckboxLabel required inline">&cb</label>') def test_flatten_fieldsets(self): Loading tests/forms_tests/tests/test_forms.py +17 −0 Original line number Diff line number Diff line Loading @@ -1846,3 +1846,20 @@ class FormsTestCase(TestCase): self.assertHTMLEqual(boundfield.label_tag(), 'Field') self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&') def test_boundfield_label_tag_custom_widget_id_for_label(self): class CustomIdForLabelTextInput(TextInput): def id_for_label(self, id): return 'custom_' + id class EmptyIdForLabelTextInput(TextInput): def id_for_label(self, id): return None class SomeForm(Form): custom = CharField(widget=CustomIdForLabelTextInput) empty = CharField(widget=EmptyIdForLabelTextInput) form = SomeForm() self.assertHTMLEqual(form['custom'].label_tag(), '<label for="custom_id_custom">Custom</label>') self.assertHTMLEqual(form['empty'].label_tag(), '<label>Empty</label>') Loading
django/forms/forms.py +4 −3 Original line number Diff line number Diff line Loading @@ -525,10 +525,11 @@ class BoundField(object): widget = self.field.widget id_ = widget.attrs.get('id') or self.auto_id if id_: id_for_label = widget.id_for_label(id_) if id_for_label: attrs = dict(attrs or {}, **{'for': id_for_label}) attrs = flatatt(attrs) if attrs else '' contents = format_html('<label for="{0}"{1}>{2}</label>', widget.id_for_label(id_), attrs, contents ) contents = format_html('<label{0}>{1}</label>', attrs, contents) else: contents = conditional_escape(contents) return mark_safe(contents) Loading
tests/admin_util/tests.py +11 −12 Original line number Diff line number Diff line Loading @@ -11,8 +11,7 @@ from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE from django.contrib.sites.models import Site from django.db import models, DEFAULT_DB_ALIAS from django import forms from django.test import TestCase from django.utils import unittest from django.test import SimpleTestCase, TestCase from django.utils.formats import localize from django.utils.safestring import mark_safe from django.utils import six Loading Loading @@ -82,7 +81,7 @@ class NestedObjectsTests(TestCase): # One for Location, one for Guest, and no query for EventGuide n.collect(objs) class UtilTests(unittest.TestCase): class UtilTests(SimpleTestCase): def test_values_from_lookup_field(self): """ Regression test for #12654: lookup_field Loading Loading @@ -151,7 +150,7 @@ class UtilTests(unittest.TestCase): # handling. display_value = display_for_field(None, models.NullBooleanField()) expected = '<img src="%sadmin/img/icon-unknown.gif" alt="None" />' % settings.STATIC_URL self.assertEqual(display_value, expected) self.assertHTMLEqual(display_value, expected) display_value = display_for_field(None, models.DecimalField()) self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) Loading Loading @@ -299,9 +298,9 @@ class UtilTests(unittest.TestCase): cb = forms.BooleanField(label=mark_safe('<i>cb</i>')) form = MyForm() self.assertEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), '<label for="id_text" class="required inline"><i>text</i>:</label>') self.assertEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i></label>') # normal strings needs to be escaped Loading @@ -310,9 +309,9 @@ class UtilTests(unittest.TestCase): cb = forms.BooleanField(label='&cb') form = MyForm() self.assertEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), '<label for="id_text" class="required inline">&text:</label>') self.assertEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), '<label for="id_cb" class="vCheckboxLabel required inline">&cb</label>') def test_flatten_fieldsets(self): Loading
tests/forms_tests/tests/test_forms.py +17 −0 Original line number Diff line number Diff line Loading @@ -1846,3 +1846,20 @@ class FormsTestCase(TestCase): self.assertHTMLEqual(boundfield.label_tag(), 'Field') self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&') def test_boundfield_label_tag_custom_widget_id_for_label(self): class CustomIdForLabelTextInput(TextInput): def id_for_label(self, id): return 'custom_' + id class EmptyIdForLabelTextInput(TextInput): def id_for_label(self, id): return None class SomeForm(Form): custom = CharField(widget=CustomIdForLabelTextInput) empty = CharField(widget=EmptyIdForLabelTextInput) form = SomeForm() self.assertHTMLEqual(form['custom'].label_tag(), '<label for="custom_id_custom">Custom</label>') self.assertHTMLEqual(form['empty'].label_tag(), '<label>Empty</label>')