Fixed #30261 -- Prevented Form._html_output() from mutating errors if hidden fields have errors.
This commit is contained in:
parent
da4923ea87
commit
49275c5488
|
@ -191,7 +191,8 @@ class BaseForm:
|
||||||
|
|
||||||
def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
|
def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
|
||||||
"Output HTML. Used by as_table(), as_ul(), as_p()."
|
"Output HTML. Used by as_table(), as_ul(), as_p()."
|
||||||
top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
|
# Errors that should be displayed above all fields.
|
||||||
|
top_errors = self.non_field_errors().copy()
|
||||||
output, hidden_fields = [], []
|
output, hidden_fields = [], []
|
||||||
|
|
||||||
for name, field in self.fields.items():
|
for name, field in self.fields.items():
|
||||||
|
|
|
@ -92,6 +92,11 @@ class ErrorList(UserList, list):
|
||||||
def as_data(self):
|
def as_data(self):
|
||||||
return ValidationError(self.data).error_list
|
return ValidationError(self.data).error_list
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
copy = super().copy()
|
||||||
|
copy.error_class = self.error_class
|
||||||
|
return copy
|
||||||
|
|
||||||
def get_json_data(self, escape_html=False):
|
def get_json_data(self, escape_html=False):
|
||||||
errors = []
|
errors = []
|
||||||
for error in self.as_data():
|
for error in self.as_data():
|
||||||
|
|
|
@ -1245,6 +1245,22 @@ value="Should escape < & > and <script>alert('xss')<
|
||||||
self.assertTrue(f.has_error(NON_FIELD_ERRORS, 'password_mismatch'))
|
self.assertTrue(f.has_error(NON_FIELD_ERRORS, 'password_mismatch'))
|
||||||
self.assertFalse(f.has_error(NON_FIELD_ERRORS, 'anything'))
|
self.assertFalse(f.has_error(NON_FIELD_ERRORS, 'anything'))
|
||||||
|
|
||||||
|
def test_html_output_with_hidden_input_field_errors(self):
|
||||||
|
class TestForm(Form):
|
||||||
|
hidden_input = CharField(widget=HiddenInput)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
self.add_error(None, 'Form error')
|
||||||
|
|
||||||
|
f = TestForm(data={})
|
||||||
|
error_dict = {
|
||||||
|
'hidden_input': ['This field is required.'],
|
||||||
|
'__all__': ['Form error'],
|
||||||
|
}
|
||||||
|
self.assertEqual(f.errors, error_dict)
|
||||||
|
f.as_table()
|
||||||
|
self.assertEqual(f.errors, error_dict)
|
||||||
|
|
||||||
def test_dynamic_construction(self):
|
def test_dynamic_construction(self):
|
||||||
# It's possible to construct a Form dynamically by adding to the self.fields
|
# It's possible to construct a Form dynamically by adding to the self.fields
|
||||||
# dictionary in __init__(). Don't forget to call Form.__init__() within the
|
# dictionary in __init__(). Don't forget to call Form.__init__() within the
|
||||||
|
|
Loading…
Reference in New Issue