Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.5.x] Fixed #20211: Document backwards-incompatible change in Bound…

…Field.label_tag

Also cleaned up label escaping and consolidated the test suite regarding
label_tag.
Backport of ab68602 from master.
  • Loading branch information...
commit 9c49e64b66994ff25980d9d0d21ce3599b17cc4b 1 parent 991432e
Baptiste Mispelon authored April 06, 2013 claudep committed April 12, 2013
4  django/forms/forms.py
@@ -503,7 +503,7 @@ def label_tag(self, contents=None, attrs=None):
503 503
 
504 504
         If attrs are given, they're used as HTML attributes on the <label> tag.
505 505
         """
506  
-        contents = contents or conditional_escape(self.label)
  506
+        contents = contents or self.label
507 507
         widget = self.field.widget
508 508
         id_ = widget.attrs.get('id') or self.auto_id
509 509
         if id_:
@@ -511,6 +511,8 @@ def label_tag(self, contents=None, attrs=None):
511 511
             contents = format_html('<label for="{0}"{1}>{2}</label>',
512 512
                                    widget.id_for_label(id_), attrs, contents
513 513
                                    )
  514
+        else:
  515
+            contents = conditional_escape(contents)
514 516
         return mark_safe(contents)
515 517
 
516 518
     def css_classes(self, extra_classes=None):
4  docs/releases/1.5.txt
@@ -697,6 +697,10 @@ Miscellaneous
697 697
   longer. If you're using ``django.contrib.redirects``, make sure
698 698
   :setting:`INSTALLED_APPS` contains ``django.contrib.sites``.
699 699
 
  700
+* :meth:`BoundField.label_tag <django.forms.BoundField.label_tag>` now
  701
+  escapes its ``contents`` argument. To avoid the HTML escaping, use
  702
+  :func:`django.utils.safestring.mark_safe` on the argument before passing it.
  703
+
700 704
 Features deprecated in 1.5
701 705
 ==========================
702 706
 
52  tests/regressiontests/forms/tests/forms.py
@@ -1612,23 +1612,6 @@ def clean(self):
1612 1612
 </form>""")
1613 1613
         self.assertEqual(Template('{{ form.password1.help_text }}').render(Context({'form': UserRegistration(auto_id=False)})), '')
1614 1614
 
1615  
-        # The label_tag() method takes an optional attrs argument: a dictionary of HTML
1616  
-        # attributes to add to the <label> tag.
1617  
-        f = UserRegistration(auto_id='id_%s')
1618  
-        form_output = []
1619  
-
1620  
-        for bf in f:
1621  
-            form_output.append(bf.label_tag(attrs={'class': 'pretty'}))
1622  
-
1623  
-        expected_form_output = [
1624  
-            '<label for="id_username" class="pretty">Username</label>',
1625  
-            '<label for="id_password1" class="pretty">Password1</label>',
1626  
-            '<label for="id_password2" class="pretty">Password2</label>',
1627  
-        ]
1628  
-        self.assertEqual(len(form_output), len(expected_form_output))
1629  
-        for i in range(len(form_output)):
1630  
-            self.assertHTMLEqual(form_output[i], expected_form_output[i])
1631  
-
1632 1615
         # To display the errors that aren't associated with a particular field -- e.g.,
1633 1616
         # the errors caused by Form.clean() -- use {{ form.non_field_errors }} in the
1634 1617
         # template. If used on its own, it is displayed as a <ul> (or an empty string, if
@@ -1797,3 +1780,38 @@ class NameForm(Form):
1797 1780
         form = NameForm(data={'name' : ['fname', 'lname']})
1798 1781
         self.assertTrue(form.is_valid())
1799 1782
         self.assertEqual(form.cleaned_data, {'name' : 'fname lname'})
  1783
+
  1784
+    def test_boundfield_label_tag(self):
  1785
+        class SomeForm(Form):
  1786
+            field = CharField()
  1787
+        boundfield = SomeForm()['field']
  1788
+
  1789
+        testcases = [  # (args, kwargs, expected)
  1790
+            # without anything: just print the <label>
  1791
+            ((), {}, '<label for="id_field">Field</label>'),
  1792
+
  1793
+            # passing just one argument: overrides the field's label
  1794
+            (('custom',), {}, '<label for="id_field">custom</label>'),
  1795
+
  1796
+            # the overriden label is escaped
  1797
+            (('custom&',), {}, '<label for="id_field">custom&amp;</label>'),
  1798
+            ((mark_safe('custom&'),), {}, '<label for="id_field">custom&</label>'),
  1799
+
  1800
+            # Passing attrs to add extra attributes on the <label>
  1801
+            ((), {'attrs': {'class': 'pretty'}}, '<label for="id_field" class="pretty">Field</label>')
  1802
+        ]
  1803
+
  1804
+        for args, kwargs, expected in testcases:
  1805
+            self.assertHTMLEqual(boundfield.label_tag(*args, **kwargs), expected)
  1806
+
  1807
+    def test_boundfield_label_tag_no_id(self):
  1808
+        """
  1809
+        If a widget has no id, label_tag just returns the text with no
  1810
+        surrounding <label>.
  1811
+        """
  1812
+        class SomeForm(Form):
  1813
+            field = CharField()
  1814
+        boundfield = SomeForm(auto_id='')['field']
  1815
+
  1816
+        self.assertHTMLEqual(boundfield.label_tag(), 'Field')
  1817
+        self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&amp;')

0 notes on commit 9c49e64

Please sign in to comment.
Something went wrong with that request. Please try again.