Django Forms: if not valid, show form with error message
If you render the same view when the form is not valid then in template you can access the form errors using form.errors
.
{% if form.errors %} {% for field in form %} {% for error in field.errors %} <div class="alert alert-danger"> <strong>{{ error|escape }}</strong> </div> {% endfor %} {% endfor %} {% for error in form.non_field_errors %} <div class="alert alert-danger"> <strong>{{ error|escape }}</strong> </div> {% endfor %}{% endif %}
An example:
def myView(request): form = myForm(request.POST or None, request.FILES or None) if request.method == 'POST': if form.is_valid(): return HttpResponseRedirect('/thanks/') return render(request, 'my_template.html', {'form': form})
views.py
from django.contrib import messages def view_name(request): if request.method == 'POST': form = form_class(request.POST) if form.is_valid(): return HttpResponseRedirect('/thanks'/) else: messages.error(request, "Error")return render(request, 'page.html', {'form':form_class()})
If you want to show the errors of the form other than that not valid just put {{form.as_p}} like what I did below
page.html
<html> <head> <script> {% if messages %} {% for message in messages %} alert('{{message}}') {% endfor %} {% endif %} </script> </head> <body> {{form.as_p}} </body></html>
UPDATE:Added a more detailed description of the formset errors.
Form.errors combines all field and non_field_errors. Therefore you can simplify the html to this:
template
{% load form_tags %} {% if form.errors %} <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert"> <div id="form_errors"> {% for key, value in form.errors.items %} <span class="fieldWrapper"> {{ key }}:{{ value }} </span> {% endfor %} </div> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> {% endif %}If you want to generalise it you can create a list_errors.html which you include in every form template. It handles form and formset errors: {% if form.errors %} <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert"> <div id="form_errors"> {% for key, value in form.errors.items %} <span class="fieldWrapper"> {{ key }}:{{ value }} </span> {% endfor %} </div> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> {% elif formset.total_error_count %} <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert"> <div id="form_errors"> {% if formset.non_form_errors %} {{ formset.non_form_errors }} {% endif %} {% for form in formset.forms %} {% if form.errors %} Form number {{ forloop.counter }}: <ul class="errorlist"> {% for key, error in form.errors.items %} <li>{{form.fields|get_label:key}} <ul class="errorlist"> <li>{{error}}</li> </ul> </li> {% endfor %} </ul> {% endif %} {% endfor %} </div> </div> {% endif %}
form_tags.py
from django import templateregister = template.Library()def get_label(a_dict, key): return getattr(a_dict.get(key), 'label', 'No label')register.filter("get_label", get_label)
One caveat: In contrast to forms Formset.errors does not include non_field_errors.