Rendering field errors in django-crispy-forms with inline forms

mpaf picture mpaf · Sep 30, 2013 · Viewed 12.8k times · Source

I'm using bootstrap3 as the default template pack in django_crispy_forms, and trying to render a form with the crispy tag:

{% crispy form %}

My form class has the following helper attributes:

class TheForm(forms.Form):
    adv_var = forms.CharField(label="variable", max_length=70)
    value = forms.FloatField()

    def __init__(self, *args, **kwargs):
        super(TheForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()

        self.helper.form_method = 'post'
        self.helper.form_class = 'form-inline'
        self.helper.field_template = 'bootstrap3/layout/inline_field.html'

        self.helper.layout = Layout(
            'adv_var', 'value',
            ButtonHolder(
                Submit('submit', 'Start', css_class='button white')
            )
        )

When posting the form with errors, re-rendering the template does not show the errors even though I can print form._errors in the view and see the list of errors.

If I change the helper.field_template to another value (or remove it to set the default) the errors are displayed above each field - but I don't get the inline display anymore.

How can I use django-crispy-forms to display all errors of this form in a separate div for example?

Answer

evilchili picture evilchili · Apr 10, 2014

We use django.contrib.messages to push a generic error string when the form has validation errors, and leave the field errors alone to render inline:

from django.contrib import messages
# ...
if not form.is_valid():
    messages.error(request, "Please correct the errors below and resubmit.")
    return render(request, template, context)

We then use bootstrap alerts to show all messages, including our generic error, though you could of course mark it up however you wanted.

But if all you want to do is move the errors into a separate block, add them to your request context:

from django.contrib import messages
# ...
if not form.is_valid():
    context['form_errors'] = form.errors
    return render(request, template, context)

and in your template:

{% crispy form %}
<div id='form-errors'>{{ form_errors }}</div>

You can then fiddle with the crispy form's helper attributes and styles to control the display of the inline errors.