
Hello Techies,
In this blog, we are going to check how to implement the Django Crispy Forms to make Forms effective and user friendly with its features. So you can make your login, registration, and other templates interactive using Django Crispy Form.
Let’s check Django crispy forms layout examples.
Table of Contents
List of contents
- Introduction (What is crispy forms?)
- Installation
- Django Basic Forms Rendering
- Django Crispy Forms Rendering
- Django Crispy Forms Field Customization
- Advance Features of Django Crispy Forms
1. Introduction (What is Django crispy forms?)
Django Crispy Forms is a third-party application used to manage Django Forms. This allows you to adjust the properties of the form (such as method and CSS class) on the back-end without rewriting the template.

2. Installation
To install Django crispy forms you need to use python package manager “pip” or “easy_install”
Use the below command to install django-crispy-forms:
pip install django-crispy-forms
Add this application to the INSTALLED_APPS list after installation. You can check out their official site to learn more about this application and more advanced options.
INSTALLED_APPS = [
... #existing apps
'crispy_forms',
]
CRISPY_TEMPLATE_PACK = 'bootstrap4'
Download compatible latest Bootstrap 4 CSS and JS files and keep them in your static folder which is always a good practice instead of adding a hosted Bootstrap CDN URL. For now, I’m using the CDN version.
Below is the base HTML that we extend to all our templates to avoid duplication.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>TechPlusLifeStyle - Django Crispy Forms</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
<div class="container">
<a class="navbar-brand" href="#">LOGO</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="{% url 'home' %}">Home
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'basic_product_view' %}">Basic Product View</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'crispy_product' %}">Crispy Product View</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Page Content -->
<div class="container">
<div class="row">
<div class="col-lg-12">
{% block content %}
{% endblock %}
</div>
</div>
</div>
<!-- Bootstrap core JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js" integrity="sha384-LtrjvnR4Twt/qOuYxE721u19sVFLVSA4hf/rRt6PrZTmiPltdZcI7q7PXQBYTKyf" crossorigin="anonymous"></script>
</body>
</html>
Below is the models.py file which we are using for both examples with and without Crispy forms.
#models.py
from django.db import models
class Products(models.Model):
class Meta:
db_table = 'products'
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=150)
price = models.DecimalField(max_digits=20, decimal_places=2, default = 0.0)
category = models.CharField(max_length=150)
description = models.TextField()
3. Django Basic Forms Rendering
Let’s check the basic form rendering without using any CSS.
The Python code to represent the product detail form is as follows.
#urls.py
from django.urls import path
from . import views
urlpatterns = [
path('basic_product/', views.BasicProductView.as_view(), name="basic_product_view"),
]
#views.py
from django.views.generic import CreateView
from .models import Products
class BasicProductView(CreateView):
model = Products
template_name = 'basic_product_view.html'
fields = ['name', 'price', 'category', 'description']
success_url = "/basic_product"
Template View
Create separate html (basic_product_view.html) for basic product view and add the below code in it. In this template we will extend the base.html and render the Create-view of Basic Product view and form.
{% extends 'base.html' %}
{% block content %}
<h1>Add Product</h1>
<form method="post" novalidate>
{% csrf_token %}
<table>{{ form }}</table>
<button type="submit" class="btn btn-success">Save</button>
</form>
{% endblock %}
Rendered HTML

Rendered HTML with validation

4. Django Crispy Forms Rendering
Template code as in the previous example using crispy_forms_tags.
Template View
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Add Product</h1>
<form method="post" novalidate>
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-success">Save</button>
</form>
{% endblock %}
Rendered HTML

Rendered HTML with validation

5. Django Crispy Forms Field Customization
If you want to customize the form field, you can manually render the field using the as_crispy_field
template filter.
Template View
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Add Product</h1>
<form method="post" novalidate>
{% csrf_token %}
<div class="row">
<div class="col-6">
{{ form.name|as_crispy_field }}
</div>
<div class="col-6">
{{ form.category|as_crispy_field }}
</div>
</div>
<div class="row">
<div class="col-6">
{{ form.price|as_crispy_field }}
</div>
</div>
<div class="row">
<div class="col-6">
{{ form.description|as_crispy_field }}
</div>
</div>
<button type="submit" class="btn btn-success">Save</button>
</form>
{% endblock %}
Rendered HTML

Rendered HTML with validation

6. Advance Features of Django Crispy Forms
Django Crispy Forms offers FormHalper classes that allow us to use form properties. So, let’s see how to use this FormHalper class and its properties.
# forms.py
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from .models import Products
class ProductForm(forms.ModelForm):
class Meta:
model = Products
fields = ['name', 'price', 'category', 'description'] # list of fields you want from model
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.attrs = {'novalidate': ''}
self.helper.form_method = 'post' # get or post method
self.helper.form_id = 'product_info'
self.helper.form_class = 'product_details'
self.helper.add_input(Submit('submit', 'Save'))
The main logic in the __init__ method.In this method we are calling the formalper class and its properties. Using the helper function we can call the form attributes like form method, form id, form class as well as we can change the label name of Submit button.
# view.py
from django.views.generic import CreateView
from .models import Products
from .forms import ProductForm
class AdvanceCrispyProductView(CreateView):
model = Products
form_class = ProductForm
template_name = 'advance_crispy_product_view.html'
success_url = "/advance_crispy_product"
Template View
Here we will call the {% crispy %}
template tag and pass form instance as a parameter.
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Add Product</h1>
{% crispy form %}
{% endblock %}
Crispy Form Layout Helpers
Let’s add a layout to the form. To get this feature we need to call the Layout helper in the __init__ method. Check the code below for this implementation.
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column
from .models import Products
class ProductForm(forms.ModelForm):
class Meta:
model = Products
fields = ['name', 'price', 'category', 'description'] # list of fields you want from model
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.attrs = {'novalidate': ''}
self.helper.form_method = 'post' # get or post method
self.helper.form_id = 'product_info'
self.helper.form_class = 'product_details'
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'),
Column('category', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
'description',
Submit('submit', 'Save')
)
Rendered HTML

Rendered HTML with validation

I hope you understand all the steps on how to use Django Crispy Forms. This application provides many additional features so that you can check out the official site.
Find the source code for Django crispy-forms Github link at https://github.com/pranalikambli/django_crispy_forms
