How to Use Bootstrap 4 Forms With Django – Crispy Forms

How to Use Bootstrap 4 Forms With Django – Crispy Forms

Integrating Bootstrap Form with Django is very easy and simple. There are lots of Django Libraries for Bootstrap. In this tutorial, we are going to use django-crispy-forms for Bootstrap Form in Django. Crispy-Forms is a great package that gives good control over rendering Bootstrap form in your Django Project.

Installing Django Crispy Forms Library

For using we Django Crispy Forms Library, we need to install it. We are installing it using pip.

pip install django-crispy-forms

Now add it to your INSTALLED_APPS and specify which Bootsrap version to use.

 INSTALLED_APPS = [
    ...

    'crispy_forms',
]

CRISPY_TEMPLATE_PACK = 'bootstrap4' 

Download and Setup Bootstrap for Django Project

You can download the latest Bootstrap 4 version from getbootstrap. Then go to the download page and get the Compiled CSS and JS version.

Or if you don’t want to download you can use hosted Bootstrap CDN

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> 

For simplicity, I will be using the CDN version. Here is my base.html going to look which is referenced in the below example –

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <title>Hello, Django Fans!</title>
  </head>
  <body>
    <div class="container">
      <div class="row justify-content-center">
        <div class="col-8">
          <h1 class="mt-2">Hello Django Fans</h1>
          <hr class="mt-0 mb-4">
          {% block content %}
          {% endblock %}
        </div>
      </div>
    </div>
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html> 

Some more useful links for Django Template –

How to use Crispy Forms in Django Template

Suppose we have a model named Product as follows –

# models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=130)
    description = models.TextField(blank=True)
    price = models.FloatField(blank=True) 

Let’s say we want to create a form to add products in the model. For that, we are using CreateView.

# views.py
from django.views.generic import CreateView
from .models import Product

class ProductCreateView(CreateView):
    model = Product
    fields = ('name', 'description', 'price') 
    template_name = 'product.html' 

In product.html file will be extended by base.html. In product.html we will render ProductCreateView and form.

<!-- product.html -->
{% extends 'base.html' %}

{% block content %}
  <form method="post">
    {% csrf_token %}
    {{ form }}
    <button type="submit" class="btn btn-success">Save person</button>
  </form>
{% endblock %} 

This is the very basic form rendering. Django will render it with no style just plain fields.

form without crispy forms
form without crispy forms

To render the same form with Bootstrap classes, do the following –

<!-- product.html --> 
{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <form method="post" novalidate>
    {% csrf_token %}
    {{ form|crispy }}
    <button type="submit" class="btn btn-success">Save Product</button>
  </form>
{% endblock %} 

After using crispy with form, you will see the result like below.

form with crispy forms
form with crispy forms

There might be some cases where you want some freedom to render form fields. You can do so by rendering the fields manually and using the as_crispy_field template filter –

<!-- product.html -->
{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <form method="post" novalidate>
    {% csrf_token %}
    <div class="row">
      <div class="col-6">
        {{ form.name|as_crispy_field }}
      </div>
      <div class="col-6">
        {{ form.price|as_crispy_field }}
      </div>
    </div>
    {{ form.description|as_crispy_field }}
    <button type="submit" class="btn btn-success">Save Product</button>
  </form>
{% endblock %} 
Crispy Form with As Crispy Fields

Crispy Forms Helpers Method

Django Crispy Form have a special class method named FormHelper which gives more control over how to render your forms.

Here is the example of UpdateView using Form –

# forms.py
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from product.models import Product

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('name', 'description', 'price')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_method = 'post' # get or post
        self.helper.add_input(Submit('submit', 'Save Product')) 

The main logic is in __init__() method. In that method we are calling the Crispy FormHelper method. Using helper function we are defining POST method to handle the form. We have also change the submit label with ‘Save Product’.

Now our view, just regular Django code:

# views.py
from django.views.generic import UpdateView
from .forms import ProductForm

class ProductUpdateView(UpdateView):
    model = Product
    form_class = ProductForm
    template_name = 'product-update.html' 

Then is our template product-update.html

<!--  product-update.html -->
{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  {% crispy form %}
{% endblock %} 

Here we can simply call the {% crispy %} template tag and pass our form instance as a parameter.

 form without crispy forms helper
form without crispy forms helper

Advanced Form Rendering using Crispy Forms

This section will explain how to use crispy form feature to handle advance form rendering.

Crispy Form Layout Helpers

We can use crispy form helper functions to achieve the same layout as image.

# forms.py
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from product.models import Product

from crispy_forms.layout import Layout, Submit, Row, Column

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('name', 'description', 'price')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_method = 'post' # get or post
        self.helper.layout = Layout(
            Row(
                Column('name', css_class='form-group col-md-6 mb-0'),
                Column('price', css_class='form-group col-md-6 mb-0'),
                css_class='form-row'
            ),
            'description',
            Submit('submit', 'Save Product')
        ) 

And if you see template implementation is very minimal. You can compare the HTML code from here.

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  {% crispy form %}
{% endblock %} 
Advanced Form Rendering using Crispy Forms - Crispy Form Layout Helpers

You can find this project on GitHub.

Share