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.
This commit is contained in:
Claude Paroz 2013-05-25 15:18:48 +02:00
parent ab61dd2829
commit be0bab1bb8
3 changed files with 32 additions and 15 deletions

View File

@ -525,10 +525,11 @@ class BoundField(object):
widget = self.field.widget widget = self.field.widget
id_ = widget.attrs.get('id') or self.auto_id id_ = widget.attrs.get('id') or self.auto_id
if 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 '' attrs = flatatt(attrs) if attrs else ''
contents = format_html('<label for="{0}"{1}>{2}</label>', contents = format_html('<label{0}>{1}</label>', attrs, contents)
widget.id_for_label(id_), attrs, contents
)
else: else:
contents = conditional_escape(contents) contents = conditional_escape(contents)
return mark_safe(contents) return mark_safe(contents)

View File

@ -11,8 +11,7 @@ from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.db import models, DEFAULT_DB_ALIAS from django.db import models, DEFAULT_DB_ALIAS
from django import forms from django import forms
from django.test import TestCase from django.test import SimpleTestCase, TestCase
from django.utils import unittest
from django.utils.formats import localize from django.utils.formats import localize
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils import six from django.utils import six
@ -82,7 +81,7 @@ class NestedObjectsTests(TestCase):
# One for Location, one for Guest, and no query for EventGuide # One for Location, one for Guest, and no query for EventGuide
n.collect(objs) n.collect(objs)
class UtilTests(unittest.TestCase): class UtilTests(SimpleTestCase):
def test_values_from_lookup_field(self): def test_values_from_lookup_field(self):
""" """
Regression test for #12654: lookup_field Regression test for #12654: lookup_field
@ -151,7 +150,7 @@ class UtilTests(unittest.TestCase):
# handling. # handling.
display_value = display_for_field(None, models.NullBooleanField()) display_value = display_for_field(None, models.NullBooleanField())
expected = '<img src="%sadmin/img/icon-unknown.gif" alt="None" />' % settings.STATIC_URL 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()) display_value = display_for_field(None, models.DecimalField())
self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE)
@ -299,10 +298,10 @@ class UtilTests(unittest.TestCase):
cb = forms.BooleanField(label=mark_safe('<i>cb</i>')) cb = forms.BooleanField(label=mark_safe('<i>cb</i>'))
form = MyForm() 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>') '<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>') '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i></label>')
# normal strings needs to be escaped # normal strings needs to be escaped
class MyForm(forms.Form): class MyForm(forms.Form):
@ -310,10 +309,10 @@ class UtilTests(unittest.TestCase):
cb = forms.BooleanField(label='&cb') cb = forms.BooleanField(label='&cb')
form = MyForm() 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>') '<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>') '<label for="id_cb" class="vCheckboxLabel required inline">&amp;cb</label>')
def test_flatten_fieldsets(self): def test_flatten_fieldsets(self):
""" """

View File

@ -1846,3 +1846,20 @@ class FormsTestCase(TestCase):
self.assertHTMLEqual(boundfield.label_tag(), 'Field') self.assertHTMLEqual(boundfield.label_tag(), 'Field')
self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&amp;') 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>')