Django Crispy Forms
Django Crispy Forms is a powerful third-party Django application that allows you to easily control the rendering behavior of your Django forms in a DRY (Don't Repeat Yourself) and elegant way. It provides tools to add CSS classes, customize layouts, and enhance form rendering with minimal effort. The current version is 2.6, and it maintains an active release cadence with several updates per year to support new Django and Python versions.
Warnings
- breaking Version 2.0 removed all built-in Bootstrap template packs. These are now standalone packages (e.g., `crispy-bootstrap5`).
- breaking Version 2.6 dropped support for Django 4.2, 5.0, and 5.1.
- breaking Version 2.5 dropped support for Python 3.8. Version 2.1 dropped support for Python 3.7.
- gotcha Crispy Forms does not include static files (CSS/JS) for template packs. You must include them yourself.
- gotcha Form validation errors may not appear if you are using complex layout objects or specific template customizations.
- gotcha Not setting `CRISPY_TEMPLATE_PACK` globally may lead to forms not rendering 'crispy' by default, or with an unexpected template pack.
Install
-
pip install django-crispy-forms -
pip install crispy-bootstrap5
Imports
- FormHelper
from crispy_forms.helper import FormHelper
- Layout
from crispy_forms.layout import Layout
- Submit
from crispy_forms.layout import Submit
- Div
from crispy_forms.layout import Div
- Row
from crispy_forms.layout import Row
- Fieldset
from crispy_forms.layout import Fieldset
Quickstart
import os
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column
# settings.py (excerpt)
# INSTALLED_APPS = [
# ...,
# 'crispy_forms',
# 'crispy_bootstrap5', # Or your chosen template pack
# ]
# CRISPY_ALLOWED_TEMPLATE_PACKS = ['bootstrap5']
# CRISPY_TEMPLATE_PACK = 'bootstrap5'
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().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Row(
Column('name', css_class='form-group col-md-6 mb-0'),
Column('email', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
'message',
Submit('submit', 'Send Message', css_class='btn btn-primary')
)
# views.py (excerpt)
# from django.shortcuts import render
# def contact_view(request):
# form = ContactForm()
# return render(request, 'contact.html', {'form': form})
# contact.html (excerpt)
# {% load crispy_forms_tags %}
# <form method="post">
# {% csrf_token %}
# {% crispy form %}
# </form>
# To make this runnable in a minimal context (not a full Django app)
# This part is for demonstration only and assumes Django is configured
# and settings above are set if running in a real project.
if __name__ == '__main__':
# This part is purely illustrative as it requires a full Django setup
# and request cycle to actually render.
# In a real Django app, you would define this in forms.py
# and then render in a template using `{% crispy form %}`
form_instance = ContactForm()
print("Quickstart Form Helper and Layout defined successfully.")
print("Remember to configure settings.py and your templates as per comments.")