NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #2699 most downloaded on PyPI
Best way to have Django DRY forms
Last release 2 months ago
29 Jul 2026
Ships fairly regularly
a new release about every 5 months
Nearly every release is documented
notes for 46 of 46 stable releases
Nothing withdrawn
no release was ever pulled
15 years old
47 releases · first in 2011
Confirmed support for Django 6.1.
Dropped support for Django 4.2, 5.0 and 5.1.
One column per quarter.
Confirmed support for Python 3.14.
Confirmed support for Django 5.2.
Fixed unexpected addition the 'active' css_class to AccordionGroup
AccordionGroup rendering then it gets an unexpected css class active.Allowed pass through of context when rendering a Fieldset layout object.
Full Changelog: 2.1...2.2
Dropped support for Django 3.2, 4.0 and 4.1.
Full Changelog: 2.0...2.1
See the 2.1 Milestone for the full change list.
As the uni-form template pack has been removed support for this has also been removed. This has resulted in the following BREAKING changes.
Removed all Bootstrap template packs. These template packs are now available as standalone packages.
To upgrade, install the required template pack and add it to your
INSTALLED_APPS setting.
Also, support for Bootstrap 5 is provided by a 3rd party package under the django-crispy-forms organisation at
crispy-bootstrap5.
Removed uni-form template pack. Uni-Form specific classes previously added to every template pack e.g. textInput are now removed.
If you require these classes, the previous behaviour can be restored by adding the following to CRISPY_CLASS_CONVERTERS in your settings file.
converters = {
"textinput": "textinput textInput",
"fileinput": "fileinput fileUpload",
"passwordinput": "textinput textInput",
}
The uni-form template pack allowed for rendering of templates using a default or inline layout. As the uni-form template
pack has been removed support for this has also been removed. This has resulted in the following BREAKING changes.
form_style attribute of FormHelper is removed.form_style positional argument to render_field() is removed.form_style positional argument to the render() method of all LayoutObjects is removed.Audit for use of render() and render_field() due to the removal of the form_style positional argument is therefore
required. For example:
# django-crispy-forms 1.x
html = my_layout_object.render(form, form_style, context)
# django-crispy-forms 2.x
html = my_layout_object.render(form, context)
Widespread use of the |safe in crispy-form templates is removed. Audit for html input in your forms
especially for Field and Prepended/Appended text. To retain the previous behaviour mark text as safe
in your project code using
mark_safe(). Refs #296.
flat_attrs() method of FormActions is removed. Attributes provided by **kwargs are now passed via the flat_attrs function during __init__() instead of with each call of render()html5_required attribute of FormHelper is removed. In all supported versions of Django the required attribute is provided by the core forms module.FormActions layout object learnt a css_id kwarg to add an id to the rendered <div>None to "".CRISPY_TEMPLATE_PACK setting is not provided.get_layout_objects() and get_field_names() functions of LayoutObject now return a list of Pointers rather than a listdataclass containing a list of posistions and the name of object/field.Release of django-crispy-forms 2.0. No changes introduced since 2.0a1.
As the uni-form template pack has been removed support for this has also been removed. This has resulted in the following BREAKING changes.
Removed all Bootstrap template packs. These template packs are now available as standalone packages.
To upgrade, install the required template pack and add it to your
INSTALLED_APPS setting.
Also, support for Bootstrap 5 is provided by a 3rd party package under the django-crispy-forms organisation at
crispy-bootstrap5.
Removed uni-form template pack. Uni-Form specific classes previously added to every template pack e.g. textInput are now removed.
If you require these classes, the previous behaviour can be restored by adding the following to CRISPY_CLASS_CONVERTERS in your settings file.
converters = {
"textinput": "textinput textInput",
"fileinput": "fileinput fileUpload",
"passwordinput": "textinput textInput",
}
The uni-form template pack allowed for rendering of templates using a default or inline layout. As the uni-form template
pack has been removed support for this has also been removed. This has resulted in the following BREAKING changes.
form_style attribute of FormHelper is removed.form_style positional argument to render_field() is removed.form_style positional argument to the render() method of all LayoutObjects is removed.Audit for use of render() and render_field() due to the removal of the form_style positional argument is therefore
required. For example:
# django-crispy-forms 1.x
html = my_layout_object.render(form, form_style, context)
# django-crispy-forms 2.x
html = my_layout_object.render(form, context)
Widespread use of the |safe in crispy-form templates is removed. Audit for html input in your forms
especially for Field and Prepended/Appended text. To retain the previous behaviour mark text as safe
in your project code using
mark_safe(). Refs #296.
flat_attrs() method of FormActions is removed. Attributes provided by **kwargs are now passed via the flat_attrs function during __init__() instead of with each call of render()html5_required attribute of FormHelper is removed. In all supported versions of Django the required attribute is provided by the core forms module.FormActions layout object learnt a css_id kwarg to add an id to the rendered <div>None to "".CRISPY_TEMPLATE_PACK setting is not provided.get_layout_objects() and get_field_names() functions of LayoutObject now return a list of Pointers rather than a listdataclass containing a list of posistions and the name of object/field.Updated meta license-file in setup.cfg by @smithdc1 in #1188
license-file in setup.cfg by @smithdc1 in #1188Full Changelog: 1.13.0...1.14.0
input_size argument to FieldWithButtons to allow customisation of the size of the input in the Bootstrap 4
template pack. (#1159)See the 1.14.0 Milestone for the full change list.
# 1.13.0 (2021-09-25) * Added support for Django 4.0
Fixed rendering of grouped checkboxes and radio inputs in the Bootstrap 4 template pack.
input_size argument to AppendedText, PrependedText and PrependedAppendedText. This allows the size of these grouped inputs to be changed in the Bootstrap 4 template pack. (#1114)See the 1.12.0 Milestone for the full change list.
Added HTML parsing tools to help testing of template packs
See the 1.11.2 Milestone for the full change list.
Added custom-select for select widgets within prepended and appended fields
custom-select for select widgets within prepended and appended fields (#1116)See the 1.11.1 Milestone for the full change list.
Implemeneted custom-select for Select widgets in the Bootstrap4 Template Pack
custom-select for Select widgets in the Bootstrap4 Template Pack (#1091)data-parent in AccodrianGroup (#1091)See the 1.11.0 Milestone for the full change list
Fixed test causing SystemCheckError in some cases.
SystemCheckError in some cases. (#1075)disabled attribute when using the Bootstrap4 template pack. (#1057)See the 1.10.0 Milestone for the full change list
See the 1.9.2 Milestone for the full change list.
Added Bootstrap 4 styling for clearable file widget.
See the 1.9.1 Milestone for the full change list.
Removed support for Django versions prior to 2.2.
See the 1.9.0 Milestone for the full change list.
Fixing FileField UI bug introduced with 1.8.0
See the 1.8.1 Milestone for the full change list.
Updated compatibility for Django 1.11, 2.1, 2.2 and 3.0 in line with Django's supported versions policy.
Updated compatibility for Django 1.11, 2.1, 2.2 and 3.0 in line with Django's supported versions policy.
Numerous improvements to the Bootstrap 4 template pack, which may now be considered mature.
Here are some changes that might affect custom templating you already have in place when using Bootstrap 4 :
FormHelper.use_custom_control = False."form-row" class in place of "row".<small>Links are to the relevant Bootstap 4 docs.</small>
See the 1.8.0 Milestone for the full change list.
See 1.7.1 Milestone for full issue list.
See 1.7.1 Milestone for full issue list.
See 1.7.1 Milestone for full issue list.
See 1.7.1 Milestone for full issue list.
Fixes compatibility with Django 2.0
See 1.7 Milestone for full issue list.
Updates compatibility for Django 1.10
See 1.6.1 Milestone for full issue list.
Adds Bootstrap 4 template pack. Improves compatibility with Django 1.9. Other small fixes.
Adds Bootstrap 4 template pack. Improves compatibility with Django 1.9. Other small fixes.
Full changes: https://github.com/maraujop/django-crispy-forms/compare/1.5.2...1.6.0
Recommended.
See 1.6.0 Milestone for full issue list.
Fixes a couple of bugs including a KeyError: u'wrapper_class' when using multiple crispy forms on a page.
Fixes a couple of bugs including a KeyError: u'wrapper_class' when using multiple crispy forms on a page.
Recommended.
See 1.5.2 Milestone for full issue list.
Massive overhaul of the test suite and a quick bug fix. Recommended.
Massive overhaul of the test suite and a quick bug fix. Recommended.
Special thanks in this release to Dmitry Dygalo @Stranger6667 for a marathon effort updating the test suite and code base.
The highlights here are compatibility with Python 3 and all currently supported versions of Django (1.4, 1.7, 1.8). We've also extended the CI coverag
The highlights here are compatibility with Python 3 and all currently supported versions of Django (1.4, 1.7, 1.8). We've also extended the CI coverage to all supported Python/Django combinations and are running against Django master to pick up future problems early.
Special thanks in this release for all the <a href="http://flattr.com/thing/512037/django-crispy-forms">supporters and donators</a>.
master. See #451, #455.template_pack in {% crispy %} tag, bootstrap3 couldn't be set that way.AccordionGroup can now be set to active=False, see #246.Media meta class work, see #263.{% specialspaceless %} to avoid breaking intended spaces and be less aggressive, see #250.FormActions layout object bootstrap3 template for correct alignment, see #279.MultiField now obeys form_show_labels, see #278.wrapper_class to bootstrap.InlineRadios, see #272.table_inline_formset.html, see #262.AppendedPrependedText, replaced by PrependedAppendedText.PrependedAppendedText when rendering a select widget, in bootstrap and bootstrap3 template packs, see #258.{% crispy_addon %} tag for form_show_labels, see #256.MultiField cannot be used with bootstrap or bootstrap3 template packs.template_pack FormHelper attribute, so that template packs can be specified at form helper level. This changes layout objects render behavior.bootstrap3.CRISPY_TEMPLATE_PACK setting optional, see #237 and #244.Special thanks in this release to James Friedman @jamesmfriedman , for his amazing support in PR #213, adding initial Bootstrap 3 support.
Special thanks in this release to James Friedman <a href="https://github.com/jamesmfriedman">@jamesmfriedman</a>, for his amazing support in PR #213, adding initial Bootstrap 3 support.
update_attributes can now work with a field name, see docs.Tab layout object attributes are applied to make sense, see #228.tests.py file into several and also splitting tests for different template packs into different tests cases, runners for template packs updated.UneditableField to bootstrap module, place where it should live, no backwards compatible import left behind.bootstrap3 template pack thanks to James Friedman, see #213 and #209.RadioSelect and CheckboxSelectMultiple widget values and texts were being localized, when they shouldn't bee, see #214.RadioSelect or CheckboxSelectMultiple they were not being rendered by crispy-forms, see #206.form_show_labels wasn't working correctly with some layout objects, see #193.Labels were not being rendered with |crispy filter, see #202.
|crispy filter, see #202.Fix default value for form_show_labels in case FormHelper doesn't define it, see #199.
form_show_labels in case FormHelper doesn't define it, see #199.override_settings for testing django 1.3.7 and adding it to Travis-ci matrix.Deprecated Tab and TabHolder imports from layout.py module, they now live in bootstrap.py module.
Special thanks in this release to Charlie Denton <a href="https://github.com/meshy">@meshy</a>, for his amazing support in PRs #189 and #190, long due.
Tab and TabHolder imports from layout.py module, they now live in bootstrap.py module.disable_csrf helper attribute, see docs.CRISPY_ALLOWED_TEMPLATE_PACKS for adding easily support for new template packs, see #192.{% crispy_addon %} tag, see #195.CRISPY_TEMPLATE_PACK optional for testsruntests.py and manage.py test, see #183.wrap_together when using it with partial slices.KeepContext context manager, see #180.FormHelper.field_template attribute, for easily override field template for a specific form/formset, see docs.bootstrap/table_inline_formset.html, that can be easily used in conjunction with FormHelper.template.FormHelper.template attribute, that easily allows to override form/formset general structure template, see docs.form_show_labels helper attribute.isinstance instead of hacky internal name checking, this way subclasses of standard fields will work out of the box with crispy-forms, see #176.Bug fix for KeepContext context manager, when crispy-forms used with Jingo/Jinja2 templates, see #179.
KeepContext context manager, when crispy-forms used with Jingo/Jinja2 templates, see #179.make test for easily running project tests, see #178.Bug fix for model formsets and inline formsets, when being rendered with a FormHelper with a layout set, where some hidden formset management fields w
FormHelper with a layout set, where some hidden formset management fields would be missing, breaking saving to database.render_hidden_fields attribute to FormHelper, see docs.render_hidden_fields attribute to FormHelper, see docs.Fixes to Container and TabHolder, affecting class variable helpers with layouts containing TabHolder or AccordionGroup objects, see #172.
Container and TabHolder, affecting class variable helpers with layouts containing TabHolder or AccordionGroup objects, see #172.KeepContext context manager, see #172.Avoid raising Exceptions in |as_crispy_field filter when not in DEBUG mode.
|as_crispy_field filter when not in DEBUG mode.css_id to avoid having a css-id attribute, see #167.LayoutSlice to layout_slice module.Added wrapper_class kwarg to Field layout object, see #163.
wrapper_class kwarg to Field layout object, see #163.Accordion and AccordionGroup bootstrap layout objects, see #162.render_crispy_form to avoid override existing context, see #153.forms list attribute, see #152.django.form.utils.flatatt to internal flatatt utils implementation, this allows adding data-attrs to FormActions and StrictButton.render_field now uses a context manager to avoid side effects when layout objects update template context. This makes context mutability safe within layout objects.greedy kwarg to filter dynamic API.|as_crispy_field filter, see #135.__delitem__, __len__ and __setitem__ in LayoutObject and DynamicLayoutHandler, this avoids pylint warnings, see #114.wrap_once, update_attributes, map and pre_map to LayoutSlice.Fixed imports to be relative to package, avoiding namespace collisions.
layout and bootstrap, see #129.utils.py to avoid breaking Python 2.5 compatibility.Bug fix, reduction of white space in crispy-forms output could mess within tags, see #127, reverting part of this reduction.
AppendedPrependedText to PrependedAppendedText.Tab and TabHolder to bootstrap.py.Bug fix help_text_inline set to True, see #117.
help_text_inline set to True, see #117.clearfix class from bootstrap templates, not necessary anymore, see #105.MultiField to work with form_show_errors helper attribute.MultiField that set error class when there were form errors, no matter if the fields with errors were contained within, see #120.FieldWithButtons now supports Field layout object as its first parameter, for setting input attributes.FieldWithButtons, field label, help_text or error messages were not being rendered, see #121.Meta.fields defined, thanks to Jean-Baptiste Juin for reporting it.AppendedText, PrependedText and AppendedPrependedText layout objects, thanks to Bojan Mihelac, see #104.FieldWithButtons and StrictButton.get_layout_objects recursive call for Python2.5 compatibility, thanks to Can Başçıl for reporting it.Update prepended and appended templates to respect hidden fields, thanks to Bojan Mihelac, see #GH-103.
InlineCheckboxes to bootstrap layout objects, for rendering checkboxes inline.BaseInput subclasses, like Submit can now have its value set to a context variable.add_input in bootstrap using the right templates, see #GH-95.Tab and TabHolder layout objects thanks to david-e, see #GH-91.error_text_inline thanks to Lee Semel for controlling how to render form errors, as a block or inline, see #GH-87.ModelMultipleChoiceField on checkboxselectmultiple, see #GH-86.AppendedText, PrependedText and AppendedPrependedText were not respecting form_show_errors helper attribute, see #GH-77.html5_required helper attribute for rendering required fields using HTML5 required attribute within the input, see #GH-72. Thanks to Lloyd Philbrook.utils.render_crispy_form function, that renders a form the crispy way in Python code. This might be useful with AJAX, testing or text generation/manipulation, see #GH-64.MultiField and Fieldset layout objects can now have any kind of attribute defined, thanks to Lloyd Philbrook, see #GH-71.Fieldset, MultiField & HTML contents lazy translatable thanks to Rivo Laks, see #GH-69.radioselect checked status when used for a FK in a ModelForm, see #GH-68.form.Meta usage, using instance fields instead of static Meta definition, so that it works when updating forms on the go, see #GH-59.LayoutObject base class that creates an interface. This allows to access nested fields easily and use list methods without know internals of the system.|classes filter that returns field's classes.FormHelper can accept a form instance as an optional first argument, from which it can build a default layout.UneditableField bootstrap layout object for uneditable fields.Field('field_name', type="hidden"), see #GH-55.form after using {% crispy %} tag, see #GH-54.attrs helper attribute, for more flexible form attributes, see #GH-48.AppendedPrependedText layout object thanks to Samuel Goldszmidt, see #GH-45.MultiWidgetField layout object by Michal Kuffa, see #GH-39.Security fix: Thread safety fixes to CrispyFieldNode thanks to Paul Oswald. This avoids leaking information between requests in multithreaded WSGI ser…
BasicNode.CrispyFieldNode thanks to Paul Oswald. This avoids leaking information between requests in multithreaded WSGI servers.control-label to AppendedText and PrependedText layout object's templates.{% crispy field %} tag can now pass attrs to MultiWidget subclasses by Michal Kuffa. attrs are set for sub-widgets. Also attrs can now be an iterable for passing different attributes to different sub-widgets. For example,this way MultiWidget's widgets get css classes set correctly.Field layout objects.ChoiceFields using non-string choices with radio buttons thanks to Rudy Mutter. See #GH-46, #GH-43 and #GH-35.|crispy and |as_crispy_field filters were not rendering errors. Thanks to @ximi for reporting it and submitting a patch. See issue #GH-28.
|crispy and |as_crispy_field filters were not rendering errors. Thanks to @ximi for reporting it and submitting a patch. See issue #GH-28.radioselect.html and checkboxselectmultiple.html templates. Thanks to Christopher Petrilli for submitting a patch for radioselect. See issue #GH-35.BaseInput subclasses like Button by @jamesmfriedman. See #GH-32.id_for_label instead of auto_id to avoid ids breaking on multiwidgets. by Daniel Izquierdo. See #GH-38.utils.py for flatting extra HTML attributes.Div layout object.input name attribute is no longer slugified if only one word is provided, respecting caps.
control-label to labels, for horizontal layout thanks to bitrut.{{ field.html_name }} instead of {{ field.name }} in field templates, so that they work with form prefixes (formwizard) by Patrick Toal.field.css_classes in bootstrap field.html instead of widget classes.Fixing a critical bug in bootstrap templates, that was breaking {% load crispy_forms_tags %}
{% load crispy_forms_tags %}Using baseinput.html template within whole_uni_form.html, to be DRY and consistent.
baseinput.html template within whole_uni_form.html, to be DRY and consistent.BaseInput subclasses like Submit can now have ids set, using css_id{% uni_form %} tag. We can now do {% uni_form form %} for rendering a form using a helper, instead of {% uni_form form form.helper %}, if the FormHelper attribute attached to the form is named helper.rendered_fields checking performance.fields or exclude, then we follow Django standards.Field layout object. You can wrap name fields within and set all kind of attributes easily or override widget template.|with_class filterform_show_errors helper attribute, that controls whether to render or not form.errorsYour coding agent can read these notes before it upgrades. Set up the MCP server →