Fixed #21962 -- Added escape_html flag to ErrorDict.as_json()
This commit is contained in:
parent
7b4743580a
commit
c23b3717be
|
@ -5,7 +5,7 @@ import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.html import format_html, format_html_join
|
from django.utils.html import format_html, format_html_join, escape
|
||||||
from django.utils.encoding import force_text, python_2_unicode_compatible
|
from django.utils.encoding import force_text, python_2_unicode_compatible
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -55,8 +55,8 @@ class ErrorDict(dict):
|
||||||
def as_data(self):
|
def as_data(self):
|
||||||
return {f: e.as_data() for f, e in self.items()}
|
return {f: e.as_data() for f, e in self.items()}
|
||||||
|
|
||||||
def as_json(self):
|
def as_json(self, escape_html=False):
|
||||||
errors = {f: json.loads(e.as_json()) for f, e in self.items()}
|
errors = {f: json.loads(e.as_json(escape_html=escape_html)) for f, e in self.items()}
|
||||||
return json.dumps(errors)
|
return json.dumps(errors)
|
||||||
|
|
||||||
def as_ul(self):
|
def as_ul(self):
|
||||||
|
@ -86,11 +86,12 @@ class ErrorList(UserList, list):
|
||||||
def as_data(self):
|
def as_data(self):
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
def as_json(self):
|
def as_json(self, escape_html=False):
|
||||||
errors = []
|
errors = []
|
||||||
for error in ValidationError(self.data).error_list:
|
for error in ValidationError(self.data).error_list:
|
||||||
|
message = list(error)[0]
|
||||||
errors.append({
|
errors.append({
|
||||||
'message': list(error)[0],
|
'message': escape(message) if escape_html else message,
|
||||||
'code': error.code or '',
|
'code': error.code or '',
|
||||||
})
|
})
|
||||||
return json.dumps(errors)
|
return json.dumps(errors)
|
||||||
|
|
|
@ -142,7 +142,7 @@ and methods with an ``as_`` prefix could render them, but it had to be done
|
||||||
the other way around in order not to break code that expects rendered error
|
the other way around in order not to break code that expects rendered error
|
||||||
messages in ``Form.errors``.
|
messages in ``Form.errors``.
|
||||||
|
|
||||||
.. method:: Form.errors.as_json()
|
.. method:: Form.errors.as_json(escape_html=False)
|
||||||
|
|
||||||
.. versionadded:: 1.7
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
|
@ -152,6 +152,17 @@ Returns the errors serialized as JSON.
|
||||||
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
|
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
|
||||||
"subject": [{"message": "This field is required.", "code": "required"}]}
|
"subject": [{"message": "This field is required.", "code": "required"}]}
|
||||||
|
|
||||||
|
By default, ``as_json()`` does not escape its output. If you are using it for
|
||||||
|
something like AJAX requests to a form view where the client interprets the
|
||||||
|
response and inserts errors into the page, you'll want to be sure to escape the
|
||||||
|
results on the client-side to avoid the possibility of a cross-site scripting
|
||||||
|
attack. It's trivial to do so using a JavaScript library like jQuery - simply
|
||||||
|
use ``$(el).text(errorText)`` rather than ``.html()``.
|
||||||
|
|
||||||
|
If for some reason you don't want to use client-side escaping, you can also
|
||||||
|
set ``escape_html=True`` and error messages will be escaped so you can use them
|
||||||
|
directly in HTML.
|
||||||
|
|
||||||
.. method:: Form.add_error(field, error)
|
.. method:: Form.add_error(field, error)
|
||||||
|
|
||||||
.. versionadded:: 1.7
|
.. versionadded:: 1.7
|
||||||
|
|
|
@ -2071,6 +2071,33 @@ class FormsTestCase(TestCase):
|
||||||
}
|
}
|
||||||
self.assertEqual(errors, control)
|
self.assertEqual(errors, control)
|
||||||
|
|
||||||
|
def test_error_dict_as_json_escape_html(self):
|
||||||
|
"""#21962 - adding html escape flag to ErrorDict"""
|
||||||
|
class MyForm(Form):
|
||||||
|
foo = CharField()
|
||||||
|
bar = CharField()
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
raise ValidationError('<p>Non-field error.</p>',
|
||||||
|
code='secret',
|
||||||
|
params={'a': 1, 'b': 2})
|
||||||
|
|
||||||
|
control = {
|
||||||
|
'foo': [{'code': 'required', 'message': 'This field is required.'}],
|
||||||
|
'bar': [{'code': 'required', 'message': 'This field is required.'}],
|
||||||
|
'__all__': [{'code': 'secret', 'message': '<p>Non-field error.</p>'}]
|
||||||
|
}
|
||||||
|
|
||||||
|
form = MyForm({})
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
|
||||||
|
errors = json.loads(form.errors.as_json())
|
||||||
|
self.assertEqual(errors, control)
|
||||||
|
|
||||||
|
errors = json.loads(form.errors.as_json(escape_html=True))
|
||||||
|
control['__all__'][0]['message'] = '<p>Non-field error.</p>'
|
||||||
|
self.assertEqual(errors, control)
|
||||||
|
|
||||||
def test_error_list(self):
|
def test_error_list(self):
|
||||||
e = ErrorList()
|
e = ErrorList()
|
||||||
e.append('Foo')
|
e.append('Foo')
|
||||||
|
|
Loading…
Reference in New Issue