Escaping values
See original GitHub issueI was surprised to see that a lot of values seem to be just piped through the |safe
filter in the templates. This effectively disables Django’s auto-escaping functionality and requires explicit escaping of values within the form definition in Python.
Compare rendering a standard Python form:
>>> from django import forms
>>> class MyForm(forms.Form):
... foobar = forms.CharField(label='Foo & bar')
...
>>> unicode(MyForm())
u'<tr><th><label for="id_foobar">Foo & bar:</label></th><td><input id="id_foobar" name="foobar" type="text" /></td></tr>'
(notice that the label has been auto-escaped to use &
)
Compare this to the output from Crispy Forms:
>>> from django.template import Template, Context
>>> template = Template('{% load crispy_forms_tags %}{% crispy form %}')
>>> template.render(Context({'form': MyForm()}))
u'\n\n<form method="post" ><div id="div_id_foobar" class="form-group"><label for="id_foobar" class="control-label requiredField">\n\t\t\t\tFoo & bar<span class="asteriskField">*</span></label><div class="controls "><input class="textinput textInput form-control" id="id_foobar" name="foobar" type="text" /> </div></div></form>\n'
(notice that the label is unsafe and outputs just &
)
To get safe and valid HTML, I need to either manually use the HTML entity:
>>> class MyForm(forms.Form):
... foobar = forms.CharField(label='Foo & bar')
Or programmatically escape it:
>>> from django.utils.html import escape
>>> class MyForm(forms.Form):
... foobar = forms.CharField(label=escape('Foo & bar'))
Note that marking the string as unsafe does not work:
>>> from django.utils.safestring import mark_for_escaping
>>> class MyForm(forms.Form):
... foobar = forms.CharField(label=mark_for_escaping('Foo & bar'))
...
>>> template.render(Context({'form': MyForm()}))
u'\n\n<form method="post" ><div id="div_id_foobar" class="form-group"><label for="id_foobar" class="control-label requiredField">\n\t\t\t\tFoo & bar<span class="asteriskField">*</span></label><div class="controls "><input class="textinput textInput form-control" id="id_foobar" name="foobar" type="text" /> </div></div></form>\n'
My understanding is that auto-escaping is best practice and that generally using mark_safe
on strings in Python that you explicitly want to avoid escaping is preferred to manually escaping the values.
Is there a particular reason Crispy Forms assumes all strings are safe? Removing this behaviour would probably be a good idea, but would be backward incompatible.
Happy to put together a pull request if necessary.
Issue Analytics
- State:
- Created 10 years ago
- Comments:11 (4 by maintainers)
Top GitHub Comments
We’ve recently discussed bumping the major version for other breaking changes. So it sounds like this is the path the project is headed.
Will be good to see what this looks like but I’m nervous about time it may take to get everything in place to deliver the changes.
I’ll try and give some thought to a plan so we have some steps we can track.
All of the
|safe
filters have now been removed from the templates except forhelp_text
. This is to maintain compatibility with Django itself. See https://docs.djangoproject.com/en/4.0/ref/forms/fields/#help-text