Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 949
mpaf Avatar asked Sep 30 '13 13:09

mpaf


2 Answers

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.

like image 197
evilchili Avatar answered Nov 10 '22 21:11

evilchili


Maybe the easier way is the next because it uses less imports...

.. in views:

if request.method == 'POST':
    form = TheForm(request.POST)
    if form.is_valid():
        form.save()
        return redirect('url_name')
    else:
        form = TheForm()
    return render(request, 'form.html', {'form': form})

... and in the form you need only:

{% load crispy_forms_tags %}
{% crispy form %}

... where 'url_name' is defined name of pattern in urlpatterns (urls.py )... that's all you need really...

Crispy is a really smart system. The system knows how can intuitively to show the form errors.

like image 1
slaff.bg Avatar answered Nov 10 '22 22:11

slaff.bg