views:

1018

answers:

4

How do I add errors to the top of a form after I cleaned the data? I have an object that needs to make a REST call to an external app (google maps) as a pre-save condition, and this can fail, which means I need my users to correct the data in the form. So I clean the data and then try to save and add to the form errors if the save doesn't work:

if request.method == "POST":
#clean form data
    try:
        profile.save()
        return HttpResponseRedirect(reverse("some_page", args=[some.args]))
    except ValueError:
        our_form.errors.__all__ = [u"error message goes here"]
return render_to_response(template_name, {"ourform": our_form,}, 
       context_instance=RequestContext(request))

This failed to return the error text in my unit-tests (which were looking for it in {{form.non_field_errors}}), and then when I run it through the debugger, the errors had not been added to the forms error dict when they reach the render_to_response line, nor anywhere else in the our_form tree. Why didn't this work? How am I supposed to add errors to the top of a form after it's been cleaned?

+2  A: 

You should raise the validationerror.

Why not put the verification within the form's clean method

class ProfileForm(forms.Form):
    def clean(self):
        try:
            #Make a call to the API and verify it works well
        except:
            raise forms.ValidationError('Your address is not locatable by Google Maps')

that way, you just need the standard form.is_valid() in the view.

Lakshman Prasad
Unfortunately it has to be more systemic, this update can happen when other parts of the system try to alter the data, so it's beyond just the one form.Otherwise, you're right, the form would be ideal.
hendrixski
+3  A: 

You really want to do this during form validation and raise a ValidationError from there... but if you're set on doing it this way you'll want to access _errors to add new messages. Try something like this:

from django.forms.util import ErrorList

our_form._errors["field_name"] = ErrorList([u"error message goes here"])
Gabriel Hurley
I need the errors at the top of the form because it's not any one field that would cause this to fail (eg. I'm combining street+city+state+zipcode and geocoding it).
hendrixski
A: 

I'm not sure how horrible of a hack this is (I've only really worked on two Django projects up until this point) but if you do something like follows you get a separate error message that is not associated with a specific field in the model:

form = NewPostForm()
if something_went_horribly_wrong():
  form.errors[''] = "You broke it!"
Geoff
+1  A: 

Non field errors can be added as 'all' key or constand NON_FIELD_ERRORS:

from django import forms
errors = my_form._errors.setdefault(forms.forms.NON_FIELD_ERRORS, forms.util.ErrorList())
errors.append("My error here")
bmihelac