django form errors. get the error without any html tags

Updated for Django 2.1

We have 4 options to access form errors in views.

  1. Form.errors

Access the errors attribute to get a dictionary of error messages:

f.errors {'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}

In this dictionary, the keys are the field names, and the values are lists of strings representing the error messages. The error messages are stored in lists because a field can have multiple error messages.

You can access errors without having to call is_valid() first. The form’s data will be validated the first time either you call is_valid() or access errors.

The validation routines will only get called once, regardless of how many times you access errors or call is_valid(). This means that if validation has side effects, those side effects will only be triggered once.

  1. Form.errors.as_data()

Returns a dict that maps fields to their original ValidationError instances.

f.errors.as_data() {'sender': [ValidationError(['Enter a valid email address.'])], 'subject': [ValidationError(['This field is required.'])]}

Use this method anytime you need to identify an error by its code. This enables things like rewriting the error’s message or writing custom logic in a view when a given error is present. It can also be used to serialize the errors in a custom format (e.g. XML); for instance, as_json() relies on as_data().

The need for the as_data() method is due to backwards compatibility. Previously ValidationError instances were lost as soon as their rendered error messages were added to the Form.errors dictionary. Ideally Form.errors would have stored ValidationError instances and methods with an as_ prefix could render them, but it had to be done the other way around in order not to break code that expects rendered error messages in Form.errors.

  1. Form.errors.as_json(escape_html=False)

Returns the errors serialized as JSON.

f.errors.as_json() {"sender": [{"message": "Enter a valid email address.", "code": "invalid"}], "subject": [{"message": "This field is required.", "code": "required"}]}

By default, as_json() does not escape its output. If you are using it for something like AJAX requests to a form view where the client interprets the response and inserts errors into the page, you’ll want to be sure to escape the results on the client-side to avoid the possibility of a cross-site scripting attack. It’s trivial to do so using a JavaScript library like jQuery - simply use $(el).text(errorText) rather than .html().

If for some reason you don’t want to use client-side escaping, you can also set escape_html=True and error messages will be escaped so you can use them directly in HTML.

  1. Form.errors.get_json_data(escape_html=False) [new in django 2.0]

f.errors.get_json_data(escape_html=False)

Returns the errors as a dictionary suitable for serializing to JSON. Form.errors.as_json() returns serialized JSON, while this returns the error data before it’s serialized.

The escape_html parameter behaves as described in Form.errors.as_json().


To access errors for a certain field, use form.field_name.errors, where "field_name" is the name of the field that generates the error.

It is still good to use a for loop, in case more than one error was generated in the field.

Crude example:

{% for error in form.email.errors %}
    <label>{{ error|escape }}  </label>
{% endfor %}
<br>
<label>Email: </label>{{ form.email }}

Some errors may not be specifically related to a certain field, for example, an error that is raised when two password fields do not match. They should be accessible by:

{{ form.non_field_errors }}

There are two new methods in Django 1.7 that would also be useful to solve this problem:

Form.errors.as_data()

>>> f.errors.as_data()
{'sender': [ValidationError(['Enter a valid email address.'])],
'subject': [ValidationError(['This field is required.'])]}

Form.errors.as_json()

>>> f.errors.as_json()
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
"subject": [{"message": "This field is required.", "code": "required"}]}

This section in the forms documentation section has all the details, namely this snippet:

{% if form.subject.errors %}
    <ol>
    {% for error in form.subject.errors %}
        <li><strong>{{ error|escape }}</strong></li>
    {% endfor %}
    </ol>
{% endif %}

Replace form with whatever you call your form class in the template. In this example, subject is a field in the form. If you want to have a separate section to summarize all the errors, simply loop through the fields:

{% if form.errors %}
   {% for field in form %}
      {% for error in field.errors %}
          {{ error|escape }}
      {% endfor %}
   {% endfor %}
{% endif %}