开发者

adding errors to Django form errors.__all__

开发者 https://www.devze.com 2022-12-19 14:06 出处:网络
How do I add errors to the top of a form after I cleaned the data? I have an object that needs to ma开发者_如何学运维ke a REST call to an external app (google maps) as a pre-save condition, and this c

How do I add errors to the top of a form after I cleaned the data? I have an object that needs to ma开发者_如何学运维ke 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?


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"])


Non field errors can be added using the constant NON_FIELD_ERRORS dictionary key (which is __all__ by default):

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


In Django 1.7 or higher, I would do:

form.add_error(field_name, "Some message")

The method add_error was added in 1.7. The form variable is the form I want to manipulate and field_name is the specific field name or None if I want an error that is not associated with a specific field.

In Django 1.6 I would do something like:

from django.forms.forms import NON_FIELD_ERRORS

errors = form._errors.setdefault(field_name, form.error_class())
errors.append("Some message")

In the code above form is the form I want to manipulate and field_name is the field name for which I want to add an error. field_name can be set to NON_FIELD_ERRORS to add an error not associated with a specific field. I use form.error_class() to generate the empty list of error messages. This is how Django 1.6 internally creates an empty list rather than instantiate ErrorList() directly.


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.


You're almost there with your original solution. Here is a base Form class I built which allows me to do the same thing, i.e. add non-field error messages to the form:

from django import forms
from django.forms.util import ErrorDict
from django.forms.forms import NON_FIELD_ERRORS 

class MyBaseForm(forms.Form):
    def add_form_error(self, message):
        if not self._errors:
            self._errors = ErrorDict()
        if not NON_FIELD_ERRORS in self._errors:
            self._errors[NON_FIELD_ERRORS] = self.error_class()
        self._errors[NON_FIELD_ERRORS].append(message)

class MyForm(MyBaseForm):
    ....

All my forms extend this class and so I can simply call the add_form_error() method to add another error message.


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!"


If the validation pertains to the data layer, then you should indeed not use form validation. Since Django 1.2 though, there exists a similar concept for Django models and this is certainly what you shoud use. See the documentation for model validation.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号