DEV Community

Cover image for Django Crispy Forms
PyMeister
PyMeister

Posted on • Edited on

Django Crispy Forms

Django Crispy Forms is a third-party package for Django that helps you create elegant, DRY forms. In this tutorial, we will go over the basics of using Django Crispy Forms to create and customize forms in your Django application.

Installing Django Crispy Forms

To get started with Django Crispy Forms, you first need to install it. You can install it using pip by running the following command:

pip install django-crispy-forms
Enter fullscreen mode Exit fullscreen mode

Once installed, add 'crispy_forms' to the INSTALLED_APPS setting in your Django project's settings.py file:

INSTALLED_APPS = [
    # ...
    'crispy_forms',
    # ...
]
Enter fullscreen mode Exit fullscreen mode

Finally, add the following to your settings.py file to tell Django to use crispy forms as the default form rendering engine:

CRISPY_TEMPLATE_PACK = 'bootstrap4'
Enter fullscreen mode Exit fullscreen mode

In this tutorial, we will be using Bootstrap 4 as our default template pack, but you can use any other template pack of your choice.

Creating a form

Now that Django Crispy Forms is installed and set up, let's create a form. In this example, we will create a simple contact form with three fields: name, email, and message.

Create a new file called forms.py in your Django app's directory and add the following code:

from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit

class ContactForm(forms.Form):
    name = forms.CharField(label='Your name', max_length=100)
    email = forms.EmailField(label='Your email')
    message = forms.CharField(label='Your message', widget=forms.Textarea)

    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_id = 'id-contact-form'
        self.helper.form_method = 'post'
        self.helper.add_input(Submit('submit', 'Send message'))
Enter fullscreen mode Exit fullscreen mode

In the above code, we define a ContactForm class that inherits from Django's forms.Form class. We define three fields: name, email, and message. We also use the crispy_forms package to create a FormHelper object, which we use to add a Submit button to the form.

Using the form in a view

Now that we have defined our form, let's use it in a view. Create a new file called views.py in your app's directory and add the following code:

from django.shortcuts import render
from .forms import ContactForm

def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            # Do something with the form data
            pass
    else:
        form = ContactForm()

    return render(request, 'contact.html', {'form': form})
Enter fullscreen mode Exit fullscreen mode

In the above code, we define a contact view that renders a contact.html template and passes a ContactForm instance to the template context. If the form is submitted via POST, we validate the form and do something with the form data if it is valid.

Rendering the form in a template

Now that we have defined the form and the view, let's render the form in a template. Create a new file called contact.html in your app's templates directory and add the following code:

{% extends 'base.html' %}

{% block content %}
  <h1>Contact us</h1>
  <form method="post" id="{{ form.helper.form_id }}">
    {% csrf_token %}
    {{ form.as_p }}
  </form>
{% endblock %}
Enter fullscreen mode Exit fullscreen mode

In the above code, we extend a base template and define a content block. We then render a h1 tag and the contact form, which is passed to the template context as form. The form.as_p method renders the form as a series of paragraphs, and we also include a CSRF token for security purposes.

Customizing the form layout

One of the advantages of using Django Crispy Forms is that it allows you to easily customize the layout of your forms. In our previous example, we used the default layout, which is a series of paragraphs. Let's customize the form layout by using Bootstrap 4's grid system.

To customize the layout of the form, we need to define a Layout object and add it to the FormHelper object. Modify the ContactForm class as follows:

from crispy_forms.layout import Layout, Field

class ContactForm(forms.Form):
    name = forms.CharField(label='Your name', max_length=100)
    email = forms.EmailField(label='Your email')
    message = forms.CharField(label='Your message', widget=forms.Textarea)

    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_id = 'id-contact-form'
        self.helper.form_method = 'post'
        self.helper.add_input(Submit('submit', 'Send message'))

        self.helper.layout = Layout(
            Field('name', css_class='form-control'),
            Field('email', css_class='form-control'),
            Field('message', css_class='form-control'),
        )
Enter fullscreen mode Exit fullscreen mode

In the above code, we define a Layout object that contains three Field objects, one for each field in the form. We also add the css_class attribute to each Field object to apply Bootstrap 4's form-control class to each input element.

Finally, let's modify the contact.html template to use Bootstrap 4's form layout. Replace the contents of the template with the following:

{% extends 'base.html' %}

{% block content %}
  <div class="container">
    <h1>Contact us</h1>
    <form method="post" id="{{ form.helper.form_id }}">
      {% crispy form %}
    </form>
  </div>
{% endblock %}
Enter fullscreen mode Exit fullscreen mode

In the above code, we wrap the form in a Bootstrap 4 container class and use the crispy template tag to render the form using the FormHelper object we defined earlier.

That's it! With Django Crispy Forms, you can create and customize forms quickly and easily, with minimal boilerplate code.

Top comments (1)

Collapse
 
vulcanwm profile image
Medea

nice!