Opened 9 years ago

Last modified 9 years ago

#25548 closed Cleanup/optimization

Can't Form.add_error() in FormView.form_valid() — at Version 1

Reported by: Antoine Catton Owned by: nobody
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 Antoine Catton)

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 (1)

comment:1 by Antoine Catton, 9 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top