crispy-bootstrap5 is the Bootstrap layer between django-crispy-forms and your HTML
Bootstrap5 template pack for django-crispy-forms
At a glance
- What is it?
- crispy-bootstrap5 is a template pack for django-crispy-forms, which means it is not a form library and not a CSS framework but the piece that renders one into the other. It adds the Bootstrap 5 specific pieces that do not exist in the older Bootstrap pack, including floating labels, accordions and toggle switches.
- Who is it for?
- Adopt crispy-bootstrap5 if you use django-crispy-forms and want your Django forms rendered as Bootstrap 5 markup, since it is the maintained pack for that combination and it tracks current Django versions. Skip it if you are on Bootstrap 4 or on plain Django templates, since the whole value is the Bootstrap rendering layer, and if you need a component library beyond forms.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 51 days ago.
- What is it written in?
- Mainly HTML, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What a template pack actually is
crispy-bootstrap5 is described in one line as a Bootstrap 5 template pack for django-crispy-forms, and that phrasing is the whole architecture.
django-crispy-forms is the layer that lets you describe a form as a layout of rows and fields in Python rather than as HTML in a template. It is a layout engine, and on its own it renders markup that follows the conventions of the framework it was written for, which historically was Bootstrap 3 and later Bootstrap 4.
A template pack is the piece that changes that rendering. It is a set of templates that django-crispy-forms uses to turn its layout objects into HTML, and swapping the pack changes the output markup without changing your form definitions.
So the relationship is: your Django form holds the fields and the validation, django-crispy-forms turns a Layout definition into a renderable structure, and the template pack decides what that structure looks like as HTML with the right CSS classes.
That is why this package's primary language is HTML. The substance of a template pack is markup, and the Python in it is thin: a few template files, a few layout objects for the widgets Bootstrap 5 introduced, and the packaging.
The installation is the usual one:
$ pip install crispy-bootstrap5The project is MIT licensed, authored by David Smith, with the default branch main and the last push on 2026-09-02. The release tags use calendar versioning: 2026.9, 2026.3 and 2025.6, which is worth noting because it tells you how the maintainers think about versions. A date-based version means a new tag when something changes, and it means you can tell from the version number whether a given release predates a Django upgrade.
Two settings, and why there are two
Using the pack takes two changes to your settings file, and the documentation is precise about which is which.
You need to update your project's settings file to add crispy_forms and crispy_bootstrap5 to your project's INSTALLED_APPS. You also need to set bootstrap5 as an allowed template pack and as the default template pack for your project.
INSTALLED_APPS = (
...
"crispy_forms",
"crispy_bootstrap5",
...
)
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"So there are two settings and they do different jobs. CRISPY_ALLOWED_TEMPLATE_PACKS is the list of packs that may be used, and CRISPY_TEMPLATE_PACK is the one that is used by default. The allowed list exists so that a pack has to be opted into explicitly, which is a security and sanity measure: a project that accidentally has another pack installed does not silently render with it.
That separation is not redundant. It is the difference between a library that says which packs are permitted and a library that says which one to use, and it lets you install both bootstrap4 and bootstrap5 during a migration and switch the default per project.
The INSTALLED_APPS entries are what make the templates discoverable. Django's app registry is how the template loader finds them, so without crispy_bootstrap5 in INSTALLED_APPS the pack exists but its templates are never found, and the symptom is a fallback to the default rendering rather than an error message.
Neither setting is Django-specific in any exotic way, which is one of the things that makes this whole approach pleasant. There is no custom configuration format, no separate file, no decorator. You add two apps and set two strings.
The three Bootstrap 5 features it adds
The What is new section describes the layout objects that exist because Bootstrap 5 introduced widgets that the older pack had no way to express.
The first is floating labels. Bootstrap 5 introduces floating labels, where the placeholder text becomes the label once you type into the field. This template pack includes a layout object to use this input type:
from crispy_bootstrap5.bootstrap5 import FloatingField
# then in your Layout
... Layout(
FloatingField("first_name"),
)The second is accordions, and here Bootstrap 5 added new features such as Accordion flush, where the accordion loses its border and sits flush with its surroundings, and Always open, where more than one panel can be expanded at a time. There is a new layout object to use them:
from crispy_bootstrap5.bootstrap5 import BS5Accordion
# then in your Layout
# if not informed, flush and always_open default to False
... Layout(
BS5Accordion(
AccordionGroup("group name", "form_field_1", "form_field_2"),
AccordionGroup("another group name", "form_field"),
flush=True,
always_open=True
)
)Note the comment in that snippet: if not informed, flush and always_open default to False. Both options are opt-in and the defaults preserve the conventional Bootstrap behaviour, which is the right choice for a compatibility pack.
The third is switches. Support is added for Switches, which are a custom checkbox rendered as a toggle switch. The widget for these fields should be a CheckboxInput:
from crispy_bootstrap5.bootstrap5 import Switch
... Layout(Switch("is_company"))That last detail is the one to get right, and it is a Django detail rather than a Bootstrap one. A Bootstrap switch is styled from an ordinary checkbox input, so the field on your Django form must use the CheckboxInput widget. If you leave the default widget for a BooleanField, which in Django is a CheckboxInput anyway, it works, but if you have overridden the widget to render something else the switch styling will not apply.
All three additions share a property worth noticing: they are pure markup and CSS, with no JavaScript involved. The switch is a checkbox with different classes, the accordion is a container with a class, the floating label is a wrapper element. That is the Bootstrap 5 approach, and it means a form built with this pack needs no client-side library to look and behave correctly.
The documentation also links each feature to the relevant Bootstrap page, which is the right way to read a template pack: the pack decides the classes, the Bootstrap documentation explains what the classes do.
Versioning, dependencies and the supported matrix
The package metadata in pyproject.toml is worth reading closely, because for a compatibility pack it says everything about who can use it.
The build backend is setuptools, requiring setuptools 77.0.3 or newer, and the project requires Python 3.10 or newer. The runtime dependencies are short and specific: django at 5.2 or newer, and django-crispy-forms at 2.3 or newer.
So the floor is Django 5.2. That is a meaningful constraint and it tells you the pack tracks current Django rather than trying to span versions. Given that the release line is dated by year and month, the maintainers are clearly keeping pace with the Django release cycle.
The classifier list makes the supported matrix explicit. Django 5.2, Django 6.0 and Django 6.1 are listed, and Python 3.10 through 3.14 are listed, so the pack covers the current Django releases across the current Python versions. The remaining classifiers are the standard ones for a web library.
The version is dynamic, taken from the __version__ attribute of the crispy_bootstrap5 package, which is the pattern that avoids the version being stated in two places.
The URLs at the bottom of the metadata point at the continuous integration workflow, the changelog on the releases page, the homepage, and the issue tracker. Pointing the changelog at the releases page rather than a changelog file in the repository is a choice that keeps the version notes next to the binaries.
That combination of dated releases and an explicit version matrix is what you want from a package whose job is to track a third-party framework's markup conventions. When Bootstrap changes a class name, this package has to change with it, and the release number tells you whether it has.
The development setup and the tooling
The contribution instructions are short and complete, which is what you want from a small package.
You check out the code and create a new virtual environment:
cd crispy-bootstrap5
python -m venv venv
source venv/bin/activateOr, if you are using pipenv:
pipenv shellThen you install the dependencies and the tests:
pip install -e '.[test]'And you run the tests with pytest.
The editable install with the test extra is the modern approach and it means the package under test is the one in your working tree rather than a copy installed into site-packages, so an edit is picked up without reinstalling.
The dependency groups in the package file show the rest of the tooling. The test group is pytest and pytest-django, and the lint group is black, isort and flake8. The isort configuration sets the profile to black, which is the standard way of making the two tools agree, since isort sorts imports and black reformats them and without that setting they fight.
The pytest configuration names the settings module for the test run, DJANGO_SETTINGS_MODULE set to tests.test_settings, which is the piece that makes pytest-django work. Django needs to be configured before it can do anything, and rather than relying on a conftest fixture to set that up, the configuration points at a dedicated settings module inside the tests package.
The repository layout is consistent with a small package. There is the crispy_bootstrap5/ package itself, a tests/ directory, a pyproject.toml, a tox.ini for running the suite against multiple environments, a MANIFEST.in for the packaging, a CHANGELOG.md and a .pre-commit-config.yaml.
The tox.ini and the pre-commit config together are a signal about how the project is maintained. Tox runs the tests in multiple environments, which matters for a package that supports a range of Python versions, and pre-commit means the formatting and lint rules are applied before a commit reaches review.
There is also a test.html file at the root, which is probably a scratch page for eyeballing the rendered output of the templates against a real browser. For a package whose output is markup, having a manual page to look at is a reasonable companion to the automated tests.
Where this sits against the alternatives
The comparison worth making is with the other ways to get Bootstrap-styled Django forms.
The first is to write the HTML yourself. Django forms render to HTML without any help, and the Bootstrap class names are short enough that a careful developer can write the markup directly. The cost is that every form in the project repeats the same markup, and a change in how you want forms to look becomes an edit in every template.
The second is a component library such as django-bootstrap5 or other third-party form renderers. Those are larger in scope, and they aim to handle more of the front end than a template pack does. This pack is narrower: it stays inside django-crispy-forms and only changes the output, which means you keep the layout API you already know and you are not committed to a different form library's conventions.
The third is django-crispy-forms with the older Bootstrap 4 pack. If you are on Bootstrap 4 and not planning to move, the older pack is the correct answer and this one is not for you. The value of this package is precisely that it tracks Bootstrap 5, and Bootstrap 5 changed enough, with floating labels and the new form controls, that the old pack could not render the new markup.
The practical argument for this pack is that it is maintained. The release line is dated, the Django matrix is current, and the CI workflow runs the suite. A template pack that is not maintained still works, until the framework underneath it changes and the markup quietly stops matching the CSS.
And the scope limit is worth stating clearly. This is a rendering layer for forms. It does not give you a navigation bar, a modal, a dropdown or a button component, and it does not bring JavaScript. If your project needs a coherent set of interactive components, that is a different package, and this one would be a component of it rather than a replacement.
The one thing to check before you adopt it is your Django version, because 5.2 is the floor, and whether you actually want Bootstrap 5's markup rather than a hand-rolled variant. If you have already built a design system around custom form markup, this pack will not fit into it, and that is a good reason to skip it.
Editorial conclusion
Adopt crispy-bootstrap5 if you use django-crispy-forms and want your Django forms rendered as Bootstrap 5 markup, since it is the maintained pack for that combination and it tracks current Django versions. Skip it if you are on Bootstrap 4 or on plain Django templates, since the whole value is the Bootstrap rendering layer, and if you need a component library beyond forms. Verify first which Django version you are on, because the package requires 5.2 or newer, and that you set both of the two template pack settings rather than only one, since the allowed list and the default are separate.
Frequently asked questions
What is crispy-bootstrap5 and how do I install it?
It is a Bootstrap 5 template pack for django-crispy-forms, meaning it renders your crispy layout definitions as Bootstrap 5 markup rather than providing forms or a CSS framework of its own. You install it with `pip install crispy-bootstrap5`, add crispy_forms and crispy_bootstrap5 to INSTALLED_APPS, and set CRISPY_ALLOWED_TEMPLATE_PACKS and CRISPY_TEMPLATE_PACK to bootstrap5.
Which Bootstrap 5 features does crispy-bootstrap5 add?
Floating labels, through a FloatingField layout object. Accordions, through a BS5Accordion layout object that supports the flush and always_open options, both defaulting to False when not set. And switches, through a Switch layout object that renders a custom checkbox as a toggle switch, where the Django field widget should be a CheckboxInput. All three are pure markup and CSS with no JavaScript involved.
How do I run the crispy-bootstrap5 tests locally?
Check out the code and create a virtual environment with `python -m venv venv` and `source venv/bin/activate`, or use `pipenv shell` if you prefer pipenv. Then install the dependencies and the test extra with `pip install -e '.[test]'` and run the tests with `pytest`. The pytest configuration sets DJANGO_SETTINGS_MODULE to tests.test_settings, and the lint group installs black, isort and flake8 with isort configured to the black profile.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/django-crispy-forms-crispy-bootstrap5)Was this useful?