diff --git a/django/forms/forms.py b/django/forms/forms.py index 0b4e0e955e..39a95f134f 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -557,7 +557,7 @@ class BoundField(object): name = self.html_name else: name = self.html_initial_name - return widget.render(name, self.value(), attrs=attrs) + return force_text(widget.render(name, self.value(), attrs=attrs)) def as_text(self, attrs=None, **kwargs): """ diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index a2be118e10..b79f53d6cb 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -22,7 +22,9 @@ from django.template import Template, Context from django.test import TestCase from django.test.utils import str_prefix from django.utils.datastructures import MultiValueDict, MergeDict -from django.utils.safestring import mark_safe +from django.utils.encoding import force_text +from django.utils.html import format_html +from django.utils.safestring import mark_safe, SafeData from django.utils import six @@ -1335,6 +1337,21 @@ class FormsTestCase(TestCase): self.assertEqual(bound['password'].value(), 'foo') self.assertEqual(unbound['password'].value(), None) + def test_boundfield_rendering(self): + """ + Python 2 issue: Test that rendering a BoundField with bytestring content + doesn't lose it's safe string status (#22950). + """ + class CustomWidget(TextInput): + def render(self, name, value, attrs=None): + return format_html(str(''), ' id=custom') + + class SampleForm(Form): + name = CharField(widget=CustomWidget) + + f = SampleForm(data={'name': 'bar'}) + self.assertIsInstance(force_text(f['name']), SafeData) + def test_initial_datetime_values(self): now = datetime.datetime.now() # Nix microseconds (since they should be ignored). #22502