Commit be0bab1b authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #11725 -- Made possible to create widget label tag without "for"

Thanks Denis Martinez for the report and initial patch, and
Sergey Kolosov for bringing the patch up to date.
parent ab61dd28
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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)
+11 −12
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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)
@@ -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
@@ -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">&amp;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">&amp;cb</label>')

    def test_flatten_fieldsets(self):
+17 −0
Original line number Diff line number Diff line
@@ -1846,3 +1846,20 @@ class FormsTestCase(TestCase):

        self.assertHTMLEqual(boundfield.label_tag(), 'Field')
        self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&amp;')

    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>')