#25548 closed Cleanup/optimization (fixed)
FormView.form_invalid() discards its form argument resulting in duplicated validation
Reported by: | Antoine Catton | Owned by: | Andrew Artajos |
---|---|---|---|
Component: | Generic views | Version: | dev |
Severity: | Normal | Keywords: | performance FormView form_invalid |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | yes | UI/UX: | no |
Description (last modified by )
Let's consider this example:
class MyView(FormView): def form_valid(self, form): value = form.cleaned_data['value'] try: do_action(value) except ValueError as e: form.add_error(None, e.message) return self.form_invalid(form) return super().form_valid(form)
The error message is ignored. The main reason being that the form in discarded in FormView.form_invalid()
. Here's the current implementation on master:
def form_invalid(self, form): """ If the form is invalid, re-render the context data with the data-filled form and errors. """ return self.render_to_response(self.get_context_data())
I propose to modify this implementation to:
def form_invalid(self, form): return self.render_to_response(self.get_context_data(form=form))
since Form.get_context_data()
is doing kwargs.setdefault('form', self.get_form())
. I did that on my view, but it does feel this is something that belongs in Django.
Also, from my little understanding of the code, this also mean that if I have a form like this:
class MyForm(Form): def clean_value(self): value = self.cleaned_data['value'] try: heavy_computation(value) except ValueError as e: raise ValidationError(e.message) return value
The heavy_computation()
is going run twice.
Change History (15)
comment:1 by , 9 years ago
Description: | modified (diff) |
---|
comment:2 by , 9 years ago
Needs tests: | set |
---|---|
Summary: | Can't Form.add_error() in FormView.form_valid() → FormView.form_invalid() discards its form argument resulting in duplicated validation |
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → Cleanup/optimization |
comment:3 by , 9 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:4 by , 9 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:5 by , 9 years ago
Owner: | set to |
---|---|
Status: | new → assigned |
comment:8 by , 9 years ago
https://github.com/django/django/pull/5620
@dudepare, you mean there should be something tricky with a unittest? I feel like I've missed something big :).
comment:9 by , 9 years ago
Needs tests: | unset |
---|---|
Patch needs improvement: | set |
Triage Stage: | Accepted → Ready for checkin |
Provided patch LGTM pending a small docstring rephrasing.
comment:12 by , 9 years ago
Could this be backported to upcoming 1.9.1 please? This is a fix for regression in 1.9, so I hope this makes sense )
comment:13 by , 9 years ago
Yes, I'll backport now. I think the only reason it wasn't is that there's no obvious indication that this is a regression (introduced in #24643).
This makes a lot of sense.