



  

django-crispy-forms 2.0 documentation

 [django-crispy-forms](#) 

 stable

 

* [Installation](index.html#document-install)

	+ [Installing django-crispy-forms](index.html#installing-django-crispy-forms)

	+ [Template packs](index.html#template-packs)

	+ [Setting media files](index.html#setting-media-files)

* [crispy filter](index.html#document-filters)

	+ [Using {% crispy %} tag because it rocks](index.html#using-crispy-tag-because-it-rocks)

* [{% crispy %} tag with forms](index.html#document-crispy_tag_forms)

	+ [Fundamentals](index.html#fundamentals)

	+ [Manipulating a helper in a view](index.html#manipulating-a-helper-in-a-view)

	+ [Rendering several forms with helpers](index.html#rendering-several-forms-with-helpers)

	+ [Change ‘\*’ required fields](index.html#change-required-fields)

	+ [Make crispy-forms fail loud](index.html#make-crispy-forms-fail-loud)

	+ [Change crispy-forms <input> default classes](index.html#change-crispy-forms-input-default-classes)

	+ [Render a form within Python code](index.html#render-a-form-within-python-code)

	+ [AJAX validation recipe](index.html#ajax-validation-recipe)

	+ [Bootstrap horizontal forms](index.html#bootstrap-horizontal-forms)

	+ [Bootstrap inline forms](index.html#bootstrap-inline-forms)

* [FormHelper](index.html#document-form_helper)

	+ [FormHelper with a form attached (Default layout)](index.html#formhelper-with-a-form-attached-default-layout)

	+ [Helper attributes you can set](index.html#helper-attributes-you-can-set)

	+ [Bootstrap Helper attributes](index.html#bootstrap-helper-attributes)

	+ [Bootstrap 3 Helper attributes](index.html#bootstrap-3-helper-attributes)

	+ [Bootstrap 4 Helper attributes](index.html#bootstrap-4-helper-attributes)

	+ [Custom Helper attributes](index.html#custom-helper-attributes)

* [Layouts](index.html#document-layouts)

	+ [Fundamentals](index.html#fundamentals)

	+ [Layout objects attributes](index.html#layout-objects-attributes)

	+ [Universal layout objects](index.html#universal-layout-objects)

	+ [Bootstrap Layout objects](index.html#bootstrap-layout-objects)

	+ [Overriding layout objects templates](index.html#overriding-layout-objects-templates)

	+ [Overriding project templates](index.html#overriding-project-templates)

	+ [Creating your own layout objects](index.html#creating-your-own-layout-objects)

	+ [Composing layouts](index.html#composing-layouts)

* [How to create your own template packs](index.html#document-template_packs)

	+ [Fundamentals](index.html#fundamentals)

	+ [Starting](index.html#starting)

* [{% crispy %} tag with formsets](index.html#document-crispy_tag_formsets)

	+ [Formsets](index.html#formsets)

	+ [Extra context](index.html#extra-context)

	+ [Custom templates and table inline formsets](index.html#custom-templates-and-table-inline-formsets)

	+ [Formset forms with different layouts](index.html#formset-forms-with-different-layouts)

* [Updating layouts on the go](index.html#document-dynamic_layouts)

	+ [Selecting layout objects with slices](index.html#selecting-layout-objects-with-slices)

	+ [wrap](index.html#wrap)

	+ [wrap\_together](index.html#wrap-together)

	+ [update\_attributes](index.html#update-attributes)

	+ [all](index.html#all)

	+ [Selecting a field name](index.html#selecting-a-field-name)

	+ [filter](index.html#filter)

	+ [filter\_by\_widget](index.html#filter-by-widget)

	+ [exclude\_by\_widget](index.html#exclude-by-widget)

	+ [Manipulating a layout](index.html#manipulating-a-layout)

* [Frequently Asked Questions](index.html#document-faq)

* [API helpers](index.html#document-api_helpers)

	+ [`FormHelper`](index.html#helper.FormHelper)

* [API Layout](index.html#document-api_layout)

	+ [`BaseInput`](index.html#layout.BaseInput)

	+ [`Button`](index.html#layout.Button)

	+ [`ButtonHolder`](index.html#layout.ButtonHolder)

	+ [`Column`](index.html#layout.Column)

	+ [`Div`](index.html#layout.Div)

	+ [`Field`](index.html#layout.Field)

	+ [`Fieldset`](index.html#layout.Fieldset)

	+ [`HTML`](index.html#layout.HTML)

	+ [`Hidden`](index.html#layout.Hidden)

	+ [`Layout`](index.html#layout.Layout)

	+ [`MultiField`](index.html#layout.MultiField)

	+ [`MultiWidgetField`](index.html#layout.MultiWidgetField)

	+ [`Pointer`](index.html#layout.Pointer)

	+ [`Reset`](index.html#layout.Reset)

	+ [`Row`](index.html#layout.Row)

	+ [`Submit`](index.html#layout.Submit)

* [API templatetags](index.html#document-api_templatetags)

	+ [`BasicNode`](index.html#templatetags.crispy_forms_tags.BasicNode)

	+ [`CrispyFormNode`](index.html#templatetags.crispy_forms_tags.CrispyFormNode)

	+ [`ForLoopSimulator`](index.html#templatetags.crispy_forms_tags.ForLoopSimulator)

	+ [`do\_uni\_form()`](index.html#templatetags.crispy_forms_tags.do_uni_form)

	+ [`whole\_uni\_form\_template()`](index.html#templatetags.crispy_forms_tags.whole_uni_form_template)

	+ [`whole\_uni\_formset\_template()`](index.html#templatetags.crispy_forms_tags.whole_uni_formset_template)

	+ [`as\_crispy\_errors()`](index.html#templatetags.crispy_forms_filters.as_crispy_errors)

	+ [`as\_crispy\_field()`](index.html#templatetags.crispy_forms_filters.as_crispy_field)

	+ [`as\_crispy\_form()`](index.html#templatetags.crispy_forms_filters.as_crispy_form)

	+ [`flatatt\_filter()`](index.html#templatetags.crispy_forms_filters.flatatt_filter)

	+ [`optgroups()`](index.html#templatetags.crispy_forms_filters.optgroups)

	+ [`uni\_form\_template()`](index.html#templatetags.crispy_forms_filters.uni_form_template)

	+ [`uni\_formset\_template()`](index.html#templatetags.crispy_forms_filters.uni_formset_template)

	+ [`CrispyFieldNode`](index.html#templatetags.crispy_forms_field.CrispyFieldNode)

	+ [`classes()`](index.html#templatetags.crispy_forms_field.classes)

	+ [`crispy\_addon()`](index.html#templatetags.crispy_forms_field.crispy_addon)

	+ [`crispy\_field()`](index.html#templatetags.crispy_forms_field.crispy_field)

	+ [`css\_class()`](index.html#templatetags.crispy_forms_field.css_class)

	+ [`is\_checkbox()`](index.html#templatetags.crispy_forms_field.is_checkbox)

	+ [`is\_checkboxselectmultiple()`](index.html#templatetags.crispy_forms_field.is_checkboxselectmultiple)

	+ [`is\_clearable\_file()`](index.html#templatetags.crispy_forms_field.is_clearable_file)

	+ [`is\_file()`](index.html#templatetags.crispy_forms_field.is_file)

	+ [`is\_multivalue()`](index.html#templatetags.crispy_forms_field.is_multivalue)

	+ [`is\_password()`](index.html#templatetags.crispy_forms_field.is_password)

	+ [`is\_radioselect()`](index.html#templatetags.crispy_forms_field.is_radioselect)

	+ [`is\_select()`](index.html#templatetags.crispy_forms_field.is_select)

	+ [`pairwise()`](index.html#templatetags.crispy_forms_field.pairwise)

* [API Bootstrap](index.html#document-api_bootstrap)

	+ [`Accordion`](index.html#crispy_forms.bootstrap.Accordion)

	+ [`AccordionGroup`](index.html#crispy_forms.bootstrap.AccordionGroup)

	+ [`Alert`](index.html#crispy_forms.bootstrap.Alert)

	+ [`AppendedText`](index.html#crispy_forms.bootstrap.AppendedText)

	+ [`Container`](index.html#crispy_forms.bootstrap.Container)

	+ [`ContainerHolder`](index.html#crispy_forms.bootstrap.ContainerHolder)

	+ [`FieldWithButtons`](index.html#crispy_forms.bootstrap.FieldWithButtons)

	+ [`FormActions`](index.html#crispy_forms.bootstrap.FormActions)

	+ [`InlineCheckboxes`](index.html#crispy_forms.bootstrap.InlineCheckboxes)

	+ [`InlineField`](index.html#crispy_forms.bootstrap.InlineField)

	+ [`InlineRadios`](index.html#crispy_forms.bootstrap.InlineRadios)

	+ [`Modal`](index.html#crispy_forms.bootstrap.Modal)

	+ [`PrependedAppendedText`](index.html#crispy_forms.bootstrap.PrependedAppendedText)

	+ [`PrependedText`](index.html#crispy_forms.bootstrap.PrependedText)

	+ [`StrictButton`](index.html#crispy_forms.bootstrap.StrictButton)

	+ [`Tab`](index.html#crispy_forms.bootstrap.Tab)

	+ [`TabHolder`](index.html#crispy_forms.bootstrap.TabHolder)

	+ [`UneditableField`](index.html#crispy_forms.bootstrap.UneditableField)

* [Contributing](index.html#document-contributing)

	+ [Setup](index.html#setup)

	+ [Build the documentation locally](index.html#build-the-documentation-locally)

	+ [Setting up topic branches and generating pull requests](index.html#setting-up-topic-branches-and-generating-pull-requests)

	+ [Pull upstream changes into your fork regularly](index.html#pull-upstream-changes-into-your-fork-regularly)

	+ [How to get your Pull Request accepted](index.html#how-to-get-your-pull-request-accepted)

[django-crispy-forms](#)

* [Docs](#) »

* django-crispy-forms 2.0 documentation

* [Edit on GitHub](https://github.com/django-crispy-forms/django-crispy-forms/blob/a79749956aa7ee3f3e275b2f47d882e40a64bca2/docs/index.rst)

---

Forms have never been this crispy[¶](#forms-have-never-been-this-crispy "Permalink to this heading")

====================================================================================================

django-crispy-forms provides you with a `|crispy` filter and `{% crispy %}` tag that will let you control the rendering behavior of your [Django](https://djangoproject.com) forms in a very elegant and DRY way. Have full control without writing custom form templates. All this without breaking the standard way of doing things in [Django](https://djangoproject.com), so it plays nice with any other form application.

User Guide[¶](#user-guide "Permalink to this heading")

------------------------------------------------------

Get the most out of django-crispy-forms

### Installation[¶](#installation "Permalink to this heading")

#### Installing django-crispy-forms[¶](#installing-django-crispy-forms "Permalink to this heading")

Install latest stable version into your python environment using pip:

```

pip install django-crispy-forms

```

If you want to install development version (unstable), you can do so doing:

```

pip install git+git://github.com/django-crispy-forms/django-crispy-forms.git@main#egg=django-crispy-forms

```

Or, if you’d like to install the development version as a git repository (so

you can `git pull` updates), use the `-e` flag with `pip install`, like

so:

```

pip install -e git+git://github.com/django-crispy-forms/django-crispy-forms.git@main#egg=django-crispy-forms

```

Once installed add `crispy\_forms` to your `INSTALLED\_APPS` in settings.py:

```

INSTALLED\_APPS = (

    ...

    'crispy\_forms',

)

```

In production environments, always activate Django template cache loader. This is available since Django 1.2 and what it does is basically load templates once, then cache the result for every subsequent render. This leads to a significant performance improvement. To see how to set it up refer to the fabulous [Django docs page](https://docs.djangoproject.com/en/2.2/ref/templates/api/#django.template.loaders.cached.Loader).

#### Template packs[¶](#template-packs "Permalink to this heading")

Since version 2.0, django-crispy-forms has built-in support for version 3 and 4 of the Bootstrap CSS framework

Version v1.x also provided template packs for:

* `bootstrap` [Bootstrap](https://getbootstrap.com) is crispy-forms’s default template pack, version 2 of the popular simple and flexible HTML, CSS, and Javascript for user interfaces from Twitter.

* `uni-form` [Uni-form](https://github.com/draganbabic/uni-form/tree/uni-form-v-1-5) is a nice looking, well structured, highly customizable, accessible and usable forms.

In addition the following template packs are available through separately maintained projects.

* `foundation` [Foundation](https://get.foundation) In the creator’s words, “The most advanced responsive front-end framework in the world.” This template pack is available through [crispy-forms-foundation](https://github.com/sveetch/crispy-forms-foundation)

* `tailwind` [Tailwind](https://tailwindcss.com) A utility first framework. This template pack is available through [crispy-tailwind](https://github.com/django-crispy-forms/crispy-tailwind)

* `Bootstrap 5` Support for newer versions of Bootstrap will be in separate template packs. This starts with version 5 and is available through [crispy-bootstrap5](https://github.com/django-crispy-forms/crispy-bootstrap5)

* `Bulma` [Bulma](https://bulma.io): the modern CSS framework that just works. This template pack is available through [crispy-bulma](https://github.com/ckrybus/crispy-bulma)

If your form CSS framework is not supported and it’s open source, you can create a `crispy-forms-templatePackName` project. Please let me know, so I can link to it. Documentation on [How to create your own template packs](index.html#template-packs) is provided.

You can set your default template pack for your project using the `CRISPY\_TEMPLATE\_PACK` Django settings variable:

```

CRISPY\_TEMPLATE\_PACK = 'uni\_form'

```

Please check the documentation of your template pack package for the correct value of the `CRISPY\_TEMPLATE\_PACK` setting (there are packages which provide more than one template pack).

#### Setting media files[¶](#setting-media-files "Permalink to this heading")

crispy-forms does not include static files. You will need to include the proper corresponding media files yourself depending on what CSS framework (Template pack) you are using. This might involve one or more CSS and JS files. Read CSS framework’s docs for help on how to set it up.

### crispy filter[¶](#crispy-filter "Permalink to this heading")

Crispy filter lets you render a form or formset using django-crispy-forms elegantly div based fields. Let’s see a usage example:

```

{% load crispy\_forms\_tags %}

<form method="post" class="my-class">

    {{ my\_formset|crispy }}

</form>

```

1. Add `{% load crispy\_forms\_tags %}` to the template.

2. Append the `|crispy` filter to your form or formset context variable.

3. Refresh and enjoy!

#### Using {% crispy %} tag because it rocks[¶](#using-crispy-tag-because-it-rocks "Permalink to this heading")

As handy as the |crispy filter is, think of it as the built-in methods: `as\_table`, `as\_ul` and `as\_p`. You cannot tune up the output. The best way to make your forms crisp is using the [{% crispy %} tag with forms](index.html#crispy-tag-forms). It will change how you do forms in Django.

### {% crispy %} tag with forms[¶](#crispy-tag-with-forms "Permalink to this heading")

django-crispy-forms implements a class called `FormHelper` that defines the form rendering behavior. Helpers give you a way to control form attributes and its layout, doing this in a programmatic way using Python. This way you write as little HTML as possible, and all your logic stays in the forms and views files.

#### Fundamentals[¶](#fundamentals "Permalink to this heading")

For the rest of this document we will use the following example form for showing how to use a helper. This form is in charge of gathering some user information:

```

class ExampleForm(forms.Form):

    like\_website = forms.TypedChoiceField(

        label = "Do you like this website?",

        choices = ((1, "Yes"), (0, "No")),

        coerce = lambda x: bool(int(x)),

        widget = forms.RadioSelect,

        initial = '1',

        required = True,

    )

    favorite\_food = forms.CharField(

        label = "What is your favorite food?",

        max\_length = 80,

        required = True,

    )

    favorite\_color = forms.CharField(

        label = "What is your favorite color?",

        max\_length = 80,

        required = True,

    )

    favorite\_number = forms.IntegerField(

        label = "Favorite number",

        required = False,

    )

    notes = forms.CharField(

        label = "Additional notes or feedback",

        required = False,

    )

```

Let’s see how helpers work step by step, with some examples explained. First you will need to import `FormHelper`:

```

from crispy\_forms.helper import FormHelper

```

Your helper can be a class level variable or an instance level variable, if you don’t know what this means you might want to read the article “[Be careful how you use static variables in forms](https://tothinkornottothink.com/post/7157151391/be-careful-how-you-use-static-variables-in-forms)”. As a rule of thumb, if you are not going to manipulate a FormHelper in your code, like in a view, you should be using a static helper, otherwise you should be using an instance level helper. If you still don’t understand the subtle differences between both, use an instance level helper, because you won’t end up suffering side effects. As in the next steps I will show you how to manipulate the form helper, so we will create an instance level helper. This is how you would do it:

```

from crispy\_forms.helper import FormHelper

class ExampleForm(forms.Form):

    [...]

    def \_\_init\_\_(self, \*args, \*\*kwargs):

        super().\_\_init\_\_(\*args, \*\*kwargs)

        self.helper = FormHelper()

```

As you can see you need to call the base class constructor using `super` and override the constructor. This helper doesn’t set any form attributes, so it’s useless. Let’s see how to set up some basic FormHelper attributes:

```

from crispy\_forms.helper import FormHelper

from crispy\_forms.layout import Submit

class ExampleForm(forms.Form):

    [...]

    def \_\_init\_\_(self, \*args, \*\*kwargs):

        super().\_\_init\_\_(\*args, \*\*kwargs)

        self.helper = FormHelper()

        self.helper.form\_id = 'id-exampleForm'

        self.helper.form\_class = 'blueForms'

        self.helper.form\_method = 'post'

        self.helper.form\_action = 'submit\_survey'

        self.helper.add\_input(Submit('submit', 'Submit'))

```

Note that we are importing a class called `Submit` that is a layout object. We will see what layout objects are in detail later on, for now on let’s just say that this adds a submit button to our form, so people can send their survey.

We’ve also done some helper magic. `FormHelper` has a list of attributes that can be set, that affect mainly form attributes. Our form will have as DOM id `id-exampleForm`, it will have as DOM CSS class `blueForms`, it will use http `POST` to send information and its action will be set to `reverse(submit\_survey)`.

Let’s see how to render the form in a template. Supposing we have the form in the template context as `example\_form`, we would render it doing:

```

{% load crispy\_forms\_tags %}

{% crispy example\_form example\_form.helper %}

```

Notice that the `{% crispy %}` tags expects two parameters: first the form variable and then the helper. In this case we use the `FormHelper` attached to the form, but you could also create a `FormHelper` instance and pass it as a context variable. Most of the time, you will want to use the helper attached. Note that if you name your `FormHelper` attribute `helper` you will only need to do:

```

{% crispy form %}

```

With the default Bootstrap 4 template pack, this is exactly the html that you would get:

```

<form action="submit_survey" class="blueForms" id="id-exampleForm" method="post">

    <input name="csrfmiddlewaretoken" type="hidden" value="evU93ufHyzX5dP5h5hgOaq96zIj8c02X">

    <div id="div_id_like_website" class="form-group">

        <label class="requiredField"> Do you like this website?<span class="asteriskField">*</span> </label>

        <div action="submit_survey" class="blueForms" id="id-exampleForm">

            <div class="custom-control custom-radio">

                <input type="radio" class="custom-control-input" name="like_website" value="1" id="id_like_website_0" required checked /> <label class="custom-control-label" for="id_like_website_0"> Yes </label>

            </div>

            <div class="custom-control custom-radio">

                <input type="radio" class="custom-control-input" name="like_website" value="0" id="id_like_website_1" required /> <label class="custom-control-label" for="id_like_website_1"> No </label>

            </div>

        </div>

    </div>

    <div id="div_id_favorite_food" class="form-group">

        <label for="id_favorite_food" class="requiredField"> What is your favorite food?<span class="asteriskField">*</span> </label>

        <div><input type="text" name="favorite_food" maxlength="80" class="textinput inputtext form-control" required id="id_favorite_food" /></div>

    </div>

    <div id="div_id_favorite_color" class="form-group">

        <label for="id_favorite_color" class="requiredField"> What is your favorite color?<span class="asteriskField">*</span> </label>

        <div><input type="text" name="favorite_color" maxlength="80" class="textinput inputtext form-control" required id="id_favorite_color" /></div>

    </div>

    <div id="div_id_favorite_number" class="form-group">

        <label for="id_favorite_number" class=""> Favorite number </label>

        <div><input type="number" name="favorite_number" class="numberinput form-control" id="id_favorite_number" /></div>

    </div>

    <div id="div_id_notes" class="form-group">

        <label for="id_notes" class=""> Additional notes or feedback </label>

        <div><input type="text" name="notes" class="textinput inputtext form-control" id="id_notes" /></div>

    </div>

    <div class="form-group">

        <div class=""><input type="submit" name="submit" value="Submit" class="btn btn-primary" id="submit-id-submit" /></div>

    </div>

</form>

```

What you’ll get is the form rendered as HTML with awesome bits. Specifically…

> 

> * Opening and closing form tags, with id, class, action and method set as in the helper:

> 

> 

> 

> ```

> <form action="submit\_survey" class="blueForms" id="id-exampleForm" method="post">

>     [...]

> </form>

> 

> ```

> * Django’s CSRF controls:

> 

> 

> 

> ```

> <input name="csrfmiddlewaretoken" type="hidden" value="evU93ufHyzX5dP5h5hgOaq96zIj8c02X">

> 

> ```

> * Submit button:

> 

> 

> 

> ```

> <div class="form-group">

>     <div class=""><input type="submit" name="submit" value="Submit" class="btn btn-primary" id="submit-id-submit" /></div>

> </div>

> 

> ```

> 

> 

> 

#### Manipulating a helper in a view[¶](#manipulating-a-helper-in-a-view "Permalink to this heading")

Let’s see how we could change any helper property in a view:

```

@login\_required()

def inbox(request, template\_name):

    example\_form = ExampleForm()

    redirect\_url = request.GET.get('next')

    # Form handling logic

    [...]

    if redirect\_url is not None:

        example\_form.helper.form\_action = reverse('submit\_survey') + '?next=' + redirectUrl

    return render\_to\_response(template\_name, {'example\_form': example\_form}, context\_instance=RequestContext(request))

```

We are changing `form\_action` helper property in case the view was called with a `next` GET parameter.

#### Rendering several forms with helpers[¶](#rendering-several-forms-with-helpers "Permalink to this heading")

Often we get asked: “How do you render two or more forms, with their respective helpers, using `{% crispy %}` tag, without having `<form>` tags rendered twice?” Easy, you need to set `form\_tag` helper property to `False` in every helper:

```

self.helper.form\_tag = False

```

Then you will have to write a little of html code surrounding the forms:

```

<form action="{% url 'submit\_survey' %}" class="my-class" method="post">

    {% crispy first\_form %}

    {% crispy second\_form %}

</form>

```

You can read a list of [Helper attributes you can set](index.html#helper-attributes) and what they are for.

#### Change ‘\*’ required fields[¶](#change-required-fields "Permalink to this heading")

If you don’t like the use of `\*` (asterisk) to denote required fields you have two options:

* Asterisks have an `asteriskField` class set. So you can hide it using CSS rule:

```

.asteriskField {

    display: none;

}

```

* Override `field.html` template with a custom one.

#### Make crispy-forms fail loud[¶](#make-crispy-forms-fail-loud "Permalink to this heading")

By default when crispy-forms encounters errors, it fails silently, logs them and continues working if possible. A settings variable called `CRISPY\_FAIL\_SILENTLY` has been added so that you can control this behavior. If you want to raise exceptions instead of logging, telling you what’s going on when you are developing in debug mode, you can set it to:

```

CRISPY\_FAIL\_SILENTLY = not DEBUG

```

#### Change crispy-forms <input> default classes[¶](#change-crispy-forms-input-default-classes "Permalink to this heading")

Django fields generate default classes, crispy-forms handles these and adds other classes for compatibility with CSS frameworks.

For example a `CharField` generates an `<input class="textinput" ...`. But in uni form we need the class to be `textInput` (with capital ‘I’), so crispy-forms leaves it like `<input class="textinput textInput"...`. All official template packs are handled automatically, but maybe you are integrating a new CSS framework, or your company’s custom one, with crispy-forms and need to change the default conversions. For this you need to use a settings variable called `CRISPY\_CLASS\_CONVERTERS`, expected to be a Python dictionary:

```

CRISPY\_CLASS\_CONVERTERS = {'textinput': "textinput inputtext"}

```

For example this setting would generate `<input class"textinput inputtext" ...`. The key of the dictionary `textinput` is the Django’s default class, the value is what you want it to be substituted with, in this case we are keeping `textinput`.

#### Render a form within Python code[¶](#render-a-form-within-python-code "Permalink to this heading")

Sometimes, it might be useful to render a form using crispy-forms within Python code, like a Django view, for that there is a nice helper `render\_crispy\_form`. The prototype of the method is `render\_crispy\_form(form, helper=None, context=None)`. You can use it like this. Remember to pass your CSRF token to the helper method using the context dictionary if you want the rendered form to be able to submit.

#### AJAX validation recipe[¶](#ajax-validation-recipe "Permalink to this heading")

You may wish to validate a crispy-form through AJAX to re-render any resulting form errors. One way to do this is to set

up a view that validates the form and renders its html using `render\_crispy\_form`. This html is then returned to the

client AJAX request. Let’s see an example.

Our server side code could be:

```

from django.template.context\_processors import csrf

from crispy\_forms.utils import render\_crispy\_form

@json\_view

def save\_example\_form(request):

    form = ExampleForm(request.POST or None)

    if form.is\_valid():

        # You could actually save through AJAX and return a success code here

        form.save()

        return {'success': True}

    ctx = {}

    ctx.update(csrf(request))

    form\_html = render\_crispy\_form(form, context=ctx)

    return {'success': False, 'form\_html': form\_html}

```

I’m using a jsonview decorator from [django-jsonview](https://github.com/jsocol/django-jsonview).

Note that you have to provide `render\_crispy\_form` the necessary CSRF token, otherwise it will not work.

In our client side using jQuery would look like:

```

var example_form = '#example-form';

$.ajax({

    url: "{% url 'save_example_form' %}",

    type: "POST",

    data: $(example_form).serialize(),

    success: function(data) {

        if (!(data['success'])) {

            // Here we replace the form, for the

            $(example_form).replaceWith(data['form_html']);

        }

        else {

            // Here you can show the user a success message or do whatever you need

            $(example_form).find('.success-message').show();

        }

    },

    error: function () {

        $(example_form).find('.error-message').show()

    }

});

```

Warning

When replacing form html, you need to bind events using `live` or `on` jQuery method.

#### Bootstrap horizontal forms[¶](#bootstrap-horizontal-forms "Permalink to this heading")

![_images/bootstrap3_horizontal_form.jpg](_images/bootstrap3_horizontal_form.jpg)

The way you do horizontal forms in Bootstrap version 3 is setting some `col-lg-X` classes in labels and divs wrapping fields. This would mean a lot of hassle updating your layout objects for settings these classes, too much verbosity. Instead some `FormHelper` attributes have been added to help you easily achieve this. You will need to set only three attributes:

```

helper.form\_class = 'form-horizontal'

helper.label\_class = 'col-lg-2'

helper.field\_class = 'col-lg-8'

helper.layout = Layout(

    'email',

    'password',

    'remember\_me',

    StrictButton('Sign in', css\_class='btn-default'),

)

```

Of course you can set your widths as you like, it doesn’t have to be exactly like this.

#### Bootstrap inline forms[¶](#bootstrap-inline-forms "Permalink to this heading")

![_images/bootstrap3_inline_form.jpg](_images/bootstrap3_inline_form.jpg)

The way you do inline forms in Bootstrap version 3 is:

```

helper.form\_class = 'form-inline'

helper.field\_template = 'bootstrap3/layout/inline\_field.html'

helper.layout = Layout(

    'email',

    'password',

    'remember\_me',

    StrictButton('Sign in', css\_class='btn-default'),

)

```

Note: The form-inline class needs to be added to the form’s <form> tag. Therefore let crispy-forms render the <form> tag or add the form-inline class manually to the <form> tag in your template.

If you need to set attributes in a field, you have to use `InlineField` instead of `Field`:

```

from crispy\_forms.bootstrap import InlineField

helper.layout = Layout(

    InlineField('email', readonly=True),

    'password',

    [...]

)

```

### FormHelper[¶](#formhelper "Permalink to this heading")

What is a `FormHelper` and how to use it, is thoroughly explained in a previous section [{% crispy %} tag with forms](index.html#crispy-tag-forms).

#### FormHelper with a form attached (Default layout)[¶](#formhelper-with-a-form-attached-default-layout "Permalink to this heading")

Since version 1.2.0 `FormHelper` optionally can be passed an instance of a form. You would do it this way:

```

from crispy\_forms.helper import FormHelper

class ExampleForm(forms.Form):

    def \_\_init\_\_(self, \*args, \*\*kwargs):

        super().\_\_init\_\_(\*args, \*\*kwargs)

        self.helper = FormHelper(self)

```

When you do this crispy-forms builds a default layout using `form.fields` for you, so you don’t have to manually list them all if your form is huge. If you later need to manipulate some bits of a big layout, using dynamic layouts is highly recommended, check [Updating layouts on the go](index.html#dynamic-layouts).

Also, now the helper is able to cross match the layout with the form instance, being able to search by widget type if you are using dynamic API.

#### Helper attributes you can set[¶](#helper-attributes-you-can-set "Permalink to this heading")

**template\_pack**Allows you to set what template pack you want to use at `FormHelper` level. This is useful for example when a website needs to render different styling forms for different use cases, like desktop website vs smartphone website.

**template**When set allows you to render a form/formset using a custom template. Default template is at `{{ TEMPLATE\_PACK }}/[whole\_uni\_form.html|whole\_uni\_formset.html]`.

**field\_template**When set allows you to render a form/formset using a custom field template. Default template is at `{{ TEMPLATE\_PACK }}/field.html`.

**form\_method = ``POST``**Specifies form method attribute. You can see it to `POST` or `GET`. Defaults to `POST`.

**form\_action**Applied to the form action attribute. Can be a named URL in your URLconf that can be executed via the {% url %} template tag. Example: ‘show\_my\_profile’. In your URLconf you could have something like:

```

url(r'^show/profile/$', 'show\_my\_profile\_view', name='show\_my\_profile')

```

You can also point it to a URL ‘/whatever/blabla/’.

Sometimes you may want to add arguments to the URL, for that you will have to do in your view:

```

from django.urls import reverse

form.helper.form\_action = reverse('url\_name', args=[event.id])

form.helper.form\_action = reverse('url\_name', kwargs={'book\_id': book.id})

```

**attrs**Added in 1.2.0, a dictionary to set any kind of form attributes. Underscores in keys are translated into hyphens. The recommended way when you need to set several form attributes in order to keep your helper tidy:

```

``{'id': 'form-id', 'data_id': '/whatever'}``

<form id="form-id" data-id="/whatever" ...>

```

**form\_id**Specifies form DOM id attribute. If no id provided then no id attribute is created on the form.

**form\_class**String containing separated CSS classes to be applied to form class attribute.

**form\_tag = True**It specifies if `<form></form>` tags should be rendered when using a Layout. If set to `False` it renders the form without the `<form></form>` tags. Defaults to `True`.

**disable\_csrf = False**Disable CSRF token, when done, crispy-forms won’t use `{% csrf\_token %}` tag. This is useful when rendering several forms using `{% crispy %}` tag and `form\_tag = False` csrf\_token gets rendered several times.

**form\_error\_title**If you are rendering a form using `{% crispy %}` tag and it has `non\_field\_errors` to display, they are rendered in a div. You can set the title of the div with this attribute. Example: “Form Errors”.

**formset\_error\_title**If you are rendering a formset using `{% crispy %}` tag and it has `non\_form\_errors` to display, they are rendered in a div. You can set the title of the div with this attribute. Example: “Formset Errors”.

**form\_show\_errors = True**Default set to `True`. It decides whether to render or not form errors. If set to `False`, form.errors will not be visible even if they happen. You have to manually render them customizing your template. This allows you to customize error output.

**render\_unmentioned\_fields = False**By default django-crispy-forms renders the layout specified if it exists strictly, which means it only renders what the layout mentions, unless your form has `Meta.fields` and `Meta.exclude` defined, in that case it uses them. If you want to render unmentioned fields (all form fields), for example if you are worried about forgetting mentioning them you have to set this property to `True`. It defaults to `False`.

**render\_hidden\_fields = False**By default django-crispy-forms renders the layout specified if it exists strictly. Sometimes you might be interested in rendering all form’s hidden fields no matter if they are mentioned or not. Useful when trying to render forms with layouts as part of a formset with hidden primary key fields. It defaults to `False`.

**render\_required\_fields = False**By default django-crispy-forms renders the layout specified if it exists strictly. Sometimes you might be interested in rendering all form’s required fields no matter if they are mentioned or not. It defaults to `False`.

**include\_media = True**By default django-crispy-forms renders all form media for you within the form. If you want to render form media yourself manually outside the form, set this to `False`. If you want to globally prevent rendering of form media, override the FormHelper class with this setting modified. It defaults to `True`.

#### Bootstrap Helper attributes[¶](#bootstrap-helper-attributes "Permalink to this heading")

There are currently some helper attributes that only have functionality for a specific template pack. This doesn’t necessarily mean that they won’t be supported for other template packs in the future.

**help\_text\_inline = False**Sets whether help texts should be rendered inline or block. If set to `True` help texts will be rendered using `help-inline` class, otherwise using `help-block`. By default text messages are rendered in block mode.

**error\_text\_inline = True**Sets whether to render error messages inline or block. If set to `True` errors will be rendered using `help-inline` class, otherwise using `help-block`. By default error messages are rendered in inline mode.

**form\_show\_labels = True**Default set to `True`. Determines whether or not to render the form’s field labels.

#### Bootstrap 3 Helper attributes[¶](#bootstrap-3-helper-attributes "Permalink to this heading")

All previous, `bootstrap` (version 2) attributes are also settable in bootstrap 3 template pack `FormHelpers`. Here are listed the ones, that are only available in `bootstrap3` template pack:

**label\_class = ‘’**Default set to `''`. This class will be applied to every label, this is very useful to do horizontal forms. Set it for example like this `label\_class = col-lg-2`.

**field\_class = ‘’**Default set to `''`. This class will be applied to every div `controls` wrapping a field. This is useful for doing horizontal forms. Set it for example like this `field\_class = col-lg-8`.

#### Bootstrap 4 Helper attributes[¶](#bootstrap-4-helper-attributes "Permalink to this heading")

All previous, `bootstrap` (version 2 and 3) attributes are also settable in bootstrap 4 template pack `FormHelpers`. Here are listed the ones, that are only available in `bootstrap4` template pack:

**use\_custom\_control = True**Enables the [optional UI customization](https://getbootstrap.com/docs/4.3/components/forms/#custom-forms) of the template pack for radio, checkbox, select and file field. Useful when you already have customization based on the default interpretation of the template pack. Setting to `False` results in the [standard bootstrap](https://getbootstrap.com/docs/4.3/components/forms/#checkboxes-and-radios) classes being applied for radio and checkbox, and Django rendering for file field. See table below for examples.

The file field requires [additional JS](https://www.w3schools.com/bootstrap4/bootstrap_forms_custom.asp#myFile) to enable its functionality, it is provided within the template pack as vanilla JS.

Defaults to `True`.

| Standard | Optional |

| [radio](_images/radio.png) | [customradio](_images/custom_radio.png) |

| [checkbox](_images/checkbox.png) | [customcheckbox](_images/custom_checkbox.png) |

| [select](_images/select.png) | [customselect](_images/custom_select.png) |

| [file](_images/file_field.png) | [customfile](_images/custom_file_field.png) |

#### Custom Helper attributes[¶](#custom-helper-attributes "Permalink to this heading")

Maybe you would like `FormHelper` to do some extra thing that is not currently supported or maybe you have a very specific use case. The good thing is that you can add extra attributes and crispy-forms will automatically inject them within template context. Let’s see an example, to make things clear.

We want some forms to have uppercase labels, and for that we would like to set a helper attribute name `labels\_uppercase` to `True` or `False`. So we go and set in our helper:

```

helper.labels\_uppercase = True

```

What will happen is crispy-forms will inject a Django template variable named `{{ labels\_uppercase }}` with its corresponding value within its templates, including `field.html`, which is the template in charge of rendering a field when using crispy-forms. So we can go into that template and customize it. We will need to get familiar with it, but it’s quite easy to follow; in the end it’s just a Django template.

When we find where labels get rendered, this chunk of code to be more precise:

```

{% if field.label and not field|is\_checkbox and form\_show\_labels %}

    <label for="{{ field.id\_for\_label }}" class="control-label {% if field.field.required %}requiredField{% endif %}">

        {{ field.label }}{% if field.field.required %}<span class="asteriskField">\*</span>{% endif %}

    </label>

{% endif %}

```

The line that we would change would end up like this:

```

{% if not labels\_uppercase %}{{ field.label }}{% else %}{{ field.label|upper }}{% endif %}{% if field.field.required %}

```

Now we only need to override field template, for that you may want to check section [Overriding layout objects templates](index.html#override-templates).

Warning

Be careful, depending on what you aim to do, sometimes using dynamic layouts is a better option, check section [Updating layouts on the go](index.html#dynamic-layouts).

### Layouts[¶](#layouts "Permalink to this heading")

#### Fundamentals[¶](#fundamentals "Permalink to this heading")

Django-crispy-forms defines another powerful class called `Layout`, which allows you to change the way the form fields are rendered. This allows you to set the order of the fields, wrap them in divs or other structures, add html, set ids, classes or attributes to whatever you want, etc. And all that without writing a custom form template, using programmatic layouts. Just attach the layout to a helper, layouts are optional, but probably the most powerful thing django-crispy-forms has to offer.

A `Layout` is constructed by layout objects, which can be thought of as form components.

All these components are explained later in [Universal layout objects](#layout-objects), what you need to know now about them is that every component renders a different template and has a different purpose. Let’s write a couple of different layouts for our form, continuing with our form class example (note that the full form is not shown again).

Let’s add a layout to our helper:

```

from crispy\_forms.helper import FormHelper

from crispy\_forms.layout import Layout, Fieldset, Submit

class ExampleForm(forms.Form):

    [...]

    def \_\_init\_\_(self, \*args, \*\*kwargs):

        super().\_\_init\_\_(\*args, \*\*kwargs)

        self.helper = FormHelper()

        self.helper.layout = Layout(

            Fieldset(

                'first arg is the legend of the fieldset',

                'like\_website',

                'favorite\_number',

                'favorite\_color',

                'favorite\_food',

                'notes'

            ),

            Submit('submit', 'Submit', css\_class='button white'),

        )

```

When we render the form now using:

```

{% load crispy\_forms\_tags %}

{% crispy example\_form %}

```

We will get the fields wrapped in a fieldset, whose legend will be set to ‘first arg is the legend of the fieldset’. The fields’ order will be: `like\_website`, `favorite\_number`, `favorite\_color`, `favorite\_food` and `notes`. We also get a submit button which will be styled with Bootstrap’s `btn btn-primary` classes.

This is just the tip of the iceberg: now imagine you want to add an explanation for what notes are, you can use `HTML` layout object:

```

Layout(

    Fieldset(

        'Tell us your favorite stuff {{ username }}',

        'like\_website',

        'favorite\_number',

        'favorite\_color',

        'favorite\_food',

        HTML("""

 <p>We use notes to get better, <strong>please help us {{ username }}</strong></p>

 """),

        'notes'

    )

)

```

As you’ll notice the fieldset legend is context aware and you can write it as if it were a chunk of a template where the form will be rendered. The `HTML` object will add a message before the notes input and it’s also context aware. Note how you can wrap layout objects into other layout objects. Layout objects `Fieldset`, `Div`, `MultiField` and `ButtonHolder` can hold other Layout objects within. Let’s do an alternative layout for the same form:

```

Layout(

    MultiField(

        'Tell us your favorite stuff {{ username }}',

        Div(

            'like\_website',

            'favorite\_number',

            css\_id = 'special-fields'

        ),

        'favorite\_color',

        'favorite\_food',

        'notes'

    )

)

```

This time we are using a `MultiField`, which is a layout object that as a general rule can be used in the same places as `Fieldset`. The main difference is that this renders all the fields wrapped in a div and when there are errors in the form submission, they are shown in a list instead of each one surrounding the field. Sometimes the best way to see what layout objects do, is just try them and play with them a little bit.

#### Layout objects attributes[¶](#layout-objects-attributes "Permalink to this heading")

All layout objects you can set kwargs that will be used as HTML attributes. For example if you want to turn autocomplete off for a field you can do:

```

Field('field\_name', autocomplete='off')

```

If you want to set html attributes, with words separated by hyphens like `data-name`, as Python doesn’t support hyphens in keyword arguments and hyphens are the usual notation in HTML, underscores will be translated into hyphens, so you would do:

```

Field('field\_name', data\_name="whatever")

```

As `class` is a reserved keyword in Python, for it you will have to use `css\_class`. For example:

```

Field('field\_name', css\_class="black-fields")

```

And id attribute is set using `css\_id`:

```

Field('field\_name', css\_id="custom\_field\_id")

```

#### Universal layout objects[¶](#universal-layout-objects "Permalink to this heading")

These ones live in module `crispy\_forms.layout`. These are layout objects that are not specific to a template pack. We’ll go one by one, showing usage examples:

* **Div**: It wraps fields in a `<div>`:

```

Div('form\_field\_1', 'form\_field\_2', 'form\_field\_3', ...)

```

**NOTE** Mainly in all layout objects you can set kwargs that will be used as HTML attributes. As `class` is a reserved keyword in Python, for it you will have to use `css\_class`. For example:

```

Div('form\_field\_1', style="background: white;", title="Explication title", css\_class="bigdivs")

```

* **HTML**: A very powerful layout object. Use it to render pure html code. In fact it behaves as a Django template and it has access to the whole context of the page where the form is being rendered. This layout object doesn’t accept any extra parameters than the html to render, you cannot set html attributes like in `Div`:

```

HTML("{% if success %} <p>Operation was successful</p> {% endif %}")

```

> 

> 

> Warning

> 

> 

> Beware that this is rendered in a standalone template, so if you are using custom templatetags or filters, don’t forget to add your `{% load custom\_tags %}`

> 

> 

> 

> 

* **Field**: Extremely useful layout object. You can use it to set attributes in a field or render a specific field with a custom template. This way you avoid having to explicitly override the field’s widget and pass an ugly `attrs` dictionary:

```

Field('password', id="password-field", css\_class="passwordfields", title="Explanation")

Field('slider', template="custom-slider.html")

```

This layout object can be used to easily extend Django’s widgets. If you want to render a Django form field as hidden you can simply do:

```

Field('field\_name', type="hidden")

```

If you need HTML5 attributes, you can easily do those using underscores `data\_name` kwarg here will become into `data-name` in your generated html:

```

Field('field\_name', data\_name="special")

```

Fields in bootstrap are wrapped in a `<div class="control-group">`. You may want to set extra classes in this div, for that do:

```

Field('field\_name', wrapper\_class="extra-class")

```

* **Submit**: Used to create a submit button. First parameter is the `name` attribute of the button, second parameter is the `value` attribute:

```

Submit('search', 'SEARCH')

```

Renders to:

```

<input type="submit" name="search" value="SEARCH" class="submit submitButton" id="submit-id-search" />

```

* **Hidden**: Used to create a hidden input:

```

Hidden('name', 'value')

```

* **Button**: Creates a button:

```

Button('name', 'value')

```

* **Reset**: Used to create a reset input:

```

reset = Reset('name', 'value')

```

* **Fieldset**: It wraps fields in a `<fieldset>`. The first parameter is the text for the fieldset legend, as we’ve said it behaves like a Django template:

```

Fieldset("Text for the legend {{ username }}",

    'form\_field\_1',

    'form\_field\_2'

)

```

* **ButtonHolder**: It wraps fields in a `<div class=”buttonHolder”>`, this is a legacy layout object from the `uni-form` template pack:

```

ButtonHolder(

    HTML('<span class="hidden">✓ Saved data</span>'),

    Submit('save', 'Save')

)

```

* **MultiField**: It wraps fields in a `<div>` with a label on top. When there are errors in the form submission it renders them in a list instead of each one surrounding the field:

```

MultiField("Text for the label {{ username }}",

    'form\_field\_1',

    'form\_field\_2'

)

```

#### Bootstrap Layout objects[¶](#bootstrap-layout-objects "Permalink to this heading")

These ones live under module `crispy\_forms.bootstrap`.

* **FormActions**: It wraps fields in a `<div class="form-actions">`. It is usually used to wrap form’s buttons:

```

FormActions(

    Submit('save', 'Save changes'),

    Button('cancel', 'Cancel')

)

```

![_images/form_actions.png](_images/form_actions.png)

* **AppendedText**: It renders a bootstrap appended text input. The first parameter is the name of the field to add appended text to, then the appended text which can be HTML like. There is an optional parameter `active`, by default set to `False`, that you can set to a boolean to render appended text active. See [input\_size](#input-size) to change the size of this input:

```

AppendedText('field\_name', 'appended text to show')

AppendedText('field\_name', '$', active=True)

```

![_images/appended_text.png](_images/appended_text.png)

* **PrependedText**: It renders a bootstrap prepended text input. The first parameter is the name of the field to add prepended text to, then the prepended text which can be HTML like. There is an optional parameter `active`, by default set to `False`, that you can set to a boolean to render prepended text active. See [input\_size](#input-size) to change the size of this input:

```

PrependedText('field\_name', '<b>Prepended text</b> to show')

PrependedText('field\_name', '@', placeholder="username")

```

![_images/prepended_text.png](_images/prepended_text.png)

* **PrependedAppendedText**: It renders a combined prepended and appended text. The first parameter is the name of the field, then the prepended text and finally the appended text. See [input\_size](#input-size) to change the size of this input:

```

PrependedAppendedText('field\_name', '$', '.00'),

```

![_images/appended_prepended_text.png](_images/appended_prepended_text.png)

* **InlineCheckboxes**: It renders a Django `forms.MultipleChoiceField` field using inline checkboxes:

```

InlineCheckboxes('field\_name')

```

![_images/inline_checkboxes.png](_images/inline_checkboxes.png)

* **InlineRadios**: It renders a Django `forms.ChoiceField` field with its widget set to `forms.RadioSelect` using inline radio buttons:

```

InlineRadios('field\_name')

```

![_images/inline_radios.jpg](_images/inline_radios.jpg)

* **StrictButton**: It renders a button using `<button>` html, not `input`. By default `type` is set to `button` and `class` is set to `btn`:

```

StrictButton("Button's content", name="go", value="go", css\_class="extra")

StrictButton('Success', css\_class="btn-success")

```

![_images/strict_button.png](_images/strict_button.png)

* **FieldWithButtons**: You can create an input connected with buttons:

```

The size of the field can be customised in the Bootstrap4 template pack by passing in the size modifier class to `input_size`.

FieldWithButtons('field_name', StrictButton("Go!"), input_size="input-group-sm")

```

![_images/field_with_buttons.png](_images/field_with_buttons.png)

* **Tab & TabHolder**: `Tab` renders a tab, different tabs need to be wrapped in a `TabHolder` for automatic JavaScript functioning, also you will need `bootstrap-tab.js` included in your static files:

```

TabHolder(

    Tab('First Tab',

        'field\_name\_1',

        Div('field\_name\_2')

    ),

    Tab('Second Tab',

        Field('field\_name\_3', css\_class="extra")

    )

)

```

![_images/tab_and_tabholder.jpg](_images/tab_and_tabholder.jpg)

* **Accordion & AccordionGroup**: `AccordionGroup` renders an accordion pane, different groups need to be wrapped in an `Accordion` for automatic JavaScript functioning, also you will need `bootstrap-tab.js` included in your static files:

```

Accordion(

    AccordionGroup('First Group',

        'radio\_buttons'

    ),

    AccordionGroup('Second Group',

        Field('field\_name\_3', css\_class="extra")

    )

)

```

![_images/accordiongroup_and_accordion.jpg](_images/accordiongroup_and_accordion.jpg)

* **Alert**: `Alert` generates markup in the form of an alert dialog:

```

Alert(content="<strong>Warning!</strong> Best check yo self, you're not looking too good.")

```

![_images/alert.png](_images/alert.png)

* **UneditableField**: `UneditableField` renders a disabled field using the bootstrap `uneditable-input` class:

```

UneditableField('text\_input', css\_class='form-control-lg')

```

![_images/field_disabled.png](_images/field_disabled.png)

* **Modal**: `Modal` displays it’s fields inside a bootstrap modal that can be customized using kwargs upon initialization.

See the bootstrap docs for more examples of modals and how to control your modal

[via attributes](https://getbootstrap.com/docs/4.0/components/modal/#via-data-attributes)

or [via javascript](https://getbootstrap.com/docs/4.0/components/modal/#via-javascript).

Only supports Bootstrap v3 or higher:

```

Layout(

    Modal(

        # email.help\_text was set during the initalization of the django form field

        Field('email', placeholder="Email", wrapper\_class="mb-0"),

        Button(

            "submit",

            "Send Reset Email",

            id="email\_reset",

            css\_class="btn-primary mt-3",

            onClick="someJavasciptFunction()", # used to submit the form

        ),

        css\_id="my\_modal\_id",

        title="This is my modal",

        title\_class="w-100 text-center",

    )

)

```

![_images/modal.png](_images/modal.png)

##### Input group size[¶](#input-group-size "Permalink to this heading")

**Input group size**: By default the standard Bootstrap input sizes are used. To adjust the size of an input group (`AppendedText`, `PrependedText`, `PrependedAppendedText`) add the appropriate CSS class:

```

# Bootstrap 3 - Inputs and spans need size class. Use `css\_class`.

PrependedText('field\_name', StrictButton("Go!"), css\_class="input-sm")

PrependedText('field\_name', StrictButton("Go!"), css\_class="input-lg")

# Bootstrap 4 - Wrapping div needs size class. Use `input\_size`.

PrependedText('field\_name', StrictButton("Go!"), input\_size="input-group-sm")

PrependedText('field\_name', StrictButton("Go!"), input\_size="input-group-lg")

```

#### Overriding layout objects templates[¶](#overriding-layout-objects-templates "Permalink to this heading")

The mentioned set of [Universal layout objects](#layout-objects) has been thoroughly designed to be flexible, standard compatible and support Django form features. Every Layout object is associated to a different template that lives in `templates/{{ TEMPLATE\_PACK\_NAME }}/layout/` directory.

Some advanced users may want to use their own templates, to adapt the layout objects to their use or necessities. There are three ways to override the template that a layout object uses.

* **Globally**: You override the template of the layout object, for all instances of that layout object you use:

```

from crispy\_forms.layout import Div

Div.template = 'my\_div\_template.html'

```

* **Individually**: You can override the template for a specific layout object in a layout:

```

Layout(

    Div(

        'field1',

        'field2',

        template='my\_div\_template.html'

    )

)

```

* **Overriding templates directory**: This means mimicking crispy-forms directory structure into your project and then copying the templates that you want to override there, finally editing those copies. If you are using this approach it’s better to just copy and edit templates you will customize instead of all.

#### Overriding project templates[¶](#overriding-project-templates "Permalink to this heading")

You need to differentiate between layout objects’ templates and django-crispy-forms templates. There are some templates that live in `templates/{{ TEMPLATE\_PACK\_NAME }}` that define the form/formset structure, how a field or errors are rendered, etc. They add very little logic and are pretty much basic wrappers for the rest of django-crispy-forms power. To override these ones you have two options:

* **template** and **field\_template** attributes in `FormHelper`: Since version 1.3.0 you can override the form/formset template and the field template using helper attributes, see section [Helper attributes you can set](index.html#helper-attributes). With this you can change one specific form or all your project forms (creating a custom FormHelper base class for example).

* **Overriding templates directory**: This works the same as explained in section [Overriding layout objects templates](#override-templates). If you are adapting crispy-forms templates to a popular open source template pack you use, submit it so more people can benefit from it.

* **Creating a TEMPLATE PACK**: You maybe want to use crispy-forms with you favorite CSS framework or your Company’s CSS. For doing so, you will need to be quite familiar with crispy-forms, layout objects and their templates. You will probably want to start off with one of the existing template packs, probably `bootstrap`. Imagine your template pack is named `chocolate`, that means you probably want your root directory named the same way. For using your template pack, you will have to set `CRISPY\_TEMPLATE\_PACK = 'chocolate'` variable in your settings file and also set `CRISPY\_ALLOWED\_TEMPLATE\_PACKS = ('bootstrap', 'chocolate')`. This way crispy-forms will know you want to use your own template pack, which is an allowed one and where to look for it.

#### Creating your own layout objects[¶](#creating-your-own-layout-objects "Permalink to this heading")

The [Universal layout objects](#layout-objects) bundled with django-crispy-forms are a set of the most seen components that build a form. You will probably be able to do anything you need combining them. Anyway, you may want to create your own components, for doing that, you will need a good grasp of django-crispy-forms. Every layout object must have a method called `render`. Its prototype should be:

```

def render(self, form, context):

```

The official layout objects live in `layout.py` and `bootstrap.py`, you may want to have a look at them to fully understand how to proceed. But in general terms, a layout object is a template rendered with some parameters passed.

If you come up with a good idea and design a layout object you think others could benefit from, please open an issue or send a pull request, so django-crispy-forms gets better.

#### Composing layouts[¶](#composing-layouts "Permalink to this heading")

Imagine you have several forms that share a big chunk of the same layout. There is a easy way you can create a `Layout`, reuse and extend it. You can have a `Layout` as a component of another `Layout`. You can build that common chunk, different ways. As a separate class:

```

class CommonLayout(Layout):

    def \_\_init\_\_(self, \*args, \*\*kwargs):

        super().\_\_init\_\_(

            MultiField("User data",

                'username',

                'lastname',

                'age'

            )

        )

```

Maybe an object instance is good enough:

```

common\_layout = Layout(

    MultiField("User data",

        'username',

        'lastname',

        'age'

    )

)

```

Then you can do:

```

helper.layout = Layout(

    CommonLayout(),

    Div(

        'favorite\_food',

        'favorite\_bread',

        css\_id = 'favorite-stuff'

    )

)

```

Or:

```

helper.layout = Layout(

    common\_layout,

    Div(

        'professional\_interests',

        'job\_description',

    )

)

```

We have defined a layout and used it as a chunk of another layout, which means that those two layouts will start the same way and then extend the layout in different ways.

### How to create your own template packs[¶](#how-to-create-your-own-template-packs "Permalink to this heading")

First you will have to name your template pack, for this you can’t use the name of one of the available template packs in crispy-forms, due to name collisions. For example, let’s say in the company we work for, a designer has come up with a CSS bootstrap internally known as `chocolate`. The company has a Django project that needs to start using `chocolate`, therefore we need to create a folder named `chocolate` within our templates directory. Check your `TEMPLATE\_DIRS` setting in Django and pick your preferred path.

Once we have that folder created, we will have to create a concrete directory hierarchy so that crispy-forms can pick it up. This is what bootstrap template pack (v2) looks like:

```

.

├── accordion-group.html

├── accordion.html

├── betterform.html

├── display_form.html

├── errors.html

├── errors_formset.html

├── * field.html

├── layout

│   ├── alert.html

│   ├── * baseinput.html

│   ├── button.html

│   ├── checkboxselectmultiple.html

│   ├── checkboxselectmultiple_inline.html

│   ├── div.html

│   ├── field_errors.html

│   ├── field_errors_block.html

│   ├── field_with_buttons.html

│   ├── fieldset.html

│   ├── formactions.html

│   ├── help_text.html

│   ├── help_text_and_errors.html

│   ├── multifield.html

│   ├── prepended_appended_text.html

│   ├── radioselect.html

│   ├── radioselect_inline.html

│   ├── tab-link.html

│   ├── tab.html

│   └── uneditable_input.html

├── table_inline_formset.html

├── * uni_form.html

├── uni_formset.html

├── * whole_uni_form.html

└── whole_uni_formset.html

```

Take it easy, don’t panic, we won’t need this many templates for our template pack. Templates are also quite simple to follow if you understand what problem crispy-forms solves. The bare minimum would be the templates marked with an asterisk.

#### Fundamentals[¶](#fundamentals "Permalink to this heading")

First, since crispy-forms 1.5.0, template packs are self contained, you cannot reference a template from a different template pack.

crispy-forms has many features, but maybe you don’t need your template pack to cover all of them. `{% crispy %}` templatetag renders forms using a global structure contained within `whole\_uni\_form.html`. However, `|crispy` filter uses `uni\_form.html`. As you’ve probably guessed, the name of the templates comes from the old days of django-uni-form. Anyway, as an example, if we don’t use `|crispy` filter, we don’t really need to maintain a `uni\_form.html` template within our template pack.

If we are planning on using formsets + `{% crispy %}` we will need a `whole\_uni\_formset.html`, instead if we use formsets + `|crispy` we will need `uni\_formset.html`.

All of these templates use a tag named `{% crispy\_field %}` that is loaded doing `{% load crispy\_forms\_field %}`, that generates the html for `<input>` using `field.html` template, but previously doing Python preparation beforehand. In case you wonder the code for this tag lives in `crispy\_forms.templatetags.crispy\_forms\_field`, together with some other stuff.

So a template pack for a very basic example covering only forms and the usage of `{% crispy %}` tag, would need 2 templates: `whole\_uni\_form.html`, `field.html`. Well, that’s not completely true, because every layout object has a template attached. So if we wanted to use `Div`, we would need `div.html`. Some are not that obvious, if you need `Submit`, you will need `baseinput.html`. Some layout objects, don’t really have a template attached, like `HTML`.

In the previous template tree, there are some templates that are there for DRY purposes, they are not really compulsory or part of a layout object, so don’t worry too much.

#### Starting[¶](#starting "Permalink to this heading")

Now your best bet is probably start copying some or all of the templates under an existing crispy-forms template pack, such as `bootstrap3`, then drop the ones you don’t need. Next step is edit those templates, and adjust the HTML/CSS making it align with `chocolate`, that sometimes means dropping/adding divs, classes and other stuff around. You can always create a form in your application, with a helper attached to that new template pack and start trying out your adaptation right away.

Currently, there is an existing template pack for crispy-forms that doesn’t live in core, developed by David Thenon as an external pluggable application named [crispy-forms-foundation](https://github.com/sveetch/crispy-forms-foundation), it’s also a good reference to check out.

Beware that crispy-forms evolves and adds new `FormHelper.attributes`, if you want to use those in the future you will have to adapt your templates adding those variables and its handling.

### {% crispy %} tag with formsets[¶](#crispy-tag-with-formsets "Permalink to this heading")

`{% crispy %}` tag supports formsets rendering too, all kind of Django formsets: formsets, modelformsets and inline formsets. In this section, it’s taken for granted that you are familiar with previous explained crispy-forms concepts in the docs, like `FormHelper`, how to set `FormHelper` attributes or render a simple form using `{% crispy %}` tag.

#### Formsets[¶](#formsets "Permalink to this heading")

It’s not the purpose of this documentation to explain how formsets work in detail, for that you should check [Django official formset docs](https://docs.djangoproject.com/en/dev/topics/forms/formsets/). Let’s start creating a formset using the previous `ExampleForm` form:

```

from django.forms.models import formset\_factory

ExampleFormSet = formset\_factory(ExampleForm, extra=3)

formset = ExampleFormSet()

```

This is how you would render the formset using default rendering, no layouts or form helpers:

```

{% crispy formset %}

```

Of course, you can still use a helper, otherwise there would be nothing crispy in this. When using a `FormHelper` with a formset compared to when you use it with a form, the main difference is that helper attributes are applied to the form structure, while the layout is applied to the formset’s forms. Let’s create a helper for our `ExampleFormSet`:

```

class ExampleFormSetHelper(FormHelper):

    def \_\_init\_\_(self, \*args, \*\*kwargs):

        super().\_\_init\_\_(\*args, \*\*kwargs)

        self.form\_method = 'post'

        self.layout = Layout(

            'favorite\_color',

            'favorite\_food',

        )

        self.render\_required\_fields = True

```

This helper is quite easy to follow. We want our form to use `POST` method, and we want `favorite\_color` to be the first field, then `favorite\_food` and finally we tell crispy to render all required fields after. Let’s go and use it, when using `{% crispy %}` tag in a template there is one main difference when rendering formsets vs forms, in this case you need to specify the helper explicitly.

This would be part of an hypothetical function view:

```

formset = ExampleFormSet()

helper = ExampleFormSetHelper()

return render(request, 'template.html', {'formset': formset, 'helper': helper})

```

Then in **template.html** you would have to do:

```

{% crispy formset helper %}

```

There are two ways you can add submit buttons to a formset. Using `FormHelper.add\_input` method:

```

helper.add\_input(Submit("submit", "Save"))

```

Or you can set `FormHelper.form\_tag` to `False` and control the formset outer structure at your will writing boring HTML:

```

<form action="{% url 'save\_formset' %}" method="POST">

    {% crispy formset helper %}

    <div class="form-actions">

        <input type="submit" name="submit" value="Save" class="btn btn-primary" id="submit-save">

    </div>

</form>

```

Finally, model formsets and inline formsets are rendered exactly the same as formsets, the only difference is how you build them in your Django code.

#### Extra context[¶](#extra-context "Permalink to this heading")

Rendering any kind of formset with crispy injects some extra context in the layout rendering so that you can do things like:

```

class ExampleFormSetHelper(FormHelper):

    def \_\_init\_\_(self, \*args, \*\*kwargs):

        super(FormHelper, self).\_\_init\_\_(\*args, \*\*kwargs)

        self.form\_method = 'post'

        self.layout = Layout(

            HTML('{% if forloop.first %} Only display text on the first iteration... {% endif %}'),

            Fieldset('Item: {{forloop.counter}}', 'field'),

            'favorite\_color',

            'favorite\_food',

        )

        self.add\_input(Submit('submit', 'Save'))

```

Basically you can access a `forloop` Django node, as if you were rendering your formsets forms using a for loop.

#### Custom templates and table inline formsets[¶](#custom-templates-and-table-inline-formsets "Permalink to this heading")

Default formset template will render your formset’s form using divs, but many times people prefer tables for formsets. Don’t worry, crispy-forms’s got you covered. `FormHelper` has an attribute named `template` that can be used to specify a custom template for rendering a form or formset, in this case a formset. Obviously when we specify a `template` attribute, we are making that helper only usable with forms or formsets.

The name of the template to use is **table\_inline\_formset.html** and you use it doing:

```

helper.template = 'bootstrap/table\_inline\_formset.html'

```

The best part is that if this template doesn’t do exactly what you want, you can copy it into your templates folder, customize it and then link your helper to your alternative version. If you think what you are missing would be valuable to others, then please submit a pull request at github.

Warning

This template doesn’t currently take into account any layout you have specified and only works with bootstrap template pack.

#### Formset forms with different layouts[¶](#formset-forms-with-different-layouts "Permalink to this heading")

By default crispy-forms formset rendering shares the same layout among all formset’s forms. This is the case 99% of the times. But maybe you want to render your formset’s forms using different layouts that you cannot achieve using the extra context injected, for that you will have to create and use a custom template. Most likely you will want to do:

```

{{ formset.management\_form|crispy }}

{% for form in formset %}

    {% crispy form %}

{% endfor %}

```

Where every `form` has a `helper` attribute from which crispy will grab the layout. In your view you will need to change the layout or use a different help for every formset’s form. Make sure that you have `form\_tag` attribute set to `False`, otherwise you will get 3 individual forms rendered.

### Updating layouts on the go[¶](#updating-layouts-on-the-go "Permalink to this heading")

Layouts can be changed, adapted and generated programmatically.

The next sections will explain how to select parts of a layout and update them. We will use this API from the `FormHelper` instance and not the layout itself. This API’s basic behavior consists of selecting the piece of the layout to manipulate and chaining methods that alter it after that.

#### Selecting layout objects with slices[¶](#selecting-layout-objects-with-slices "Permalink to this heading")

You can get a slice of a layout using familiar `[]` Python operator:

```

form.helper[1:3]

form.helper[2]

form.helper[:-1]

```

You can basically do all kind of slices, the same ones supported by Python’s lists. You can also concatenate them. If you had this layout:

```

Layout(

    Div('email')

)

```

You could access `'email'` string doing:

```

form.helper[0][0]

```

#### wrap[¶](#wrap "Permalink to this heading")

One useful action you can apply on a slice is `wrap`, which wraps every selected field using a layout object type and parameters passed. Let’s see an example. If We had this layout:

```

Layout(

    'field\_1',

    'field\_2',

    'field\_3'

)

```

We could do:

```

form.helper[1:3].wrap(Field, css\_class="hello")

```

We would end up having this layout:

```

Layout(

    'field\_1',

    Field('field\_2', css\_class='hello'),

    Field('field\_3', css\_class='hello')

)

```

Note how `wrap` affects each layout object selected, if you would like to wrap `field\_2` and `field\_3` together in a `Field` layout object you will have to use [wrap\_together](#wrap-together).

Beware that the slice `[1:3]` only looks in the first level of depth of the layout. So if the previous layout was this way:

```

Layout(

    'field\_1',

    Div('field\_2'),

    'field\_3'

)

```

`helper[1:3]` would return this layout:

```

Layout(

    'field\_1',

    Field(Div('field\_2'), css\_class="hello"),

    Field('field\_3', css\_class="hello")

)

```

Parameters passed to `wrap` or `wrap\_together` will be used for creating the layout object that is wrapping selected fields. You can pass `args` and `kwargs`. If you are using a layout object like `Fieldset` which needs a string as compulsory first argument, wrap will not work as desired unless you provide the text of the legend as an argument to `wrap`. Let’s see a valid example:

```

form.helper[1:3].wrap(Fieldset, "legend of the fieldset")

```

Also you can pass `args` and `kwargs`:

```

form.helper[1:3].wrap(Fieldset, "legend of the fieldset", css\_class="fieldsets")

```

#### wrap\_together[¶](#wrap-together "Permalink to this heading")

`wrap\_together` wraps a whole slice within a layout object type with parameters passed. Let’s see an example. If We had this layout:

```

Layout(

    'field\_1',

    'field\_2',

    'field\_3'

)

```

We could do:

```

form.helper[0:3].wrap\_together(Field, css\_class="hello")

```

We would end up having this layout:

```

Layout(

    Field(

        'field\_1',

        'field\_2',

        'field\_3',

        css\_class='hello'

    )

)

```

#### update\_attributes[¶](#update-attributes "Permalink to this heading")

Updates attributes of every layout object contained in a slice:

```

Layout(

    'field\_1',

    Field('field\_2'),

    Field('field\_3')

)

```

We could do:

```

form.helper[0:3].update\_attributes(css\_class="hello")

```

Layout would turn into:

```

Layout(

    'field\_1',

    Field('field\_2', css\_class='hello'),

    Field('field\_3', css\_class='hello')

)

```

We can also apply it to a field name wrapped in a layout object:

```

form.helper['field\_2'].update\_attributes(css\_class="hello")

```

However, the following wouldn’t be correct:

```

form.helper['field\_1'].update\_attributes(css\_class="hello")

```

Because it would change `Layout` attrs. It’s your job to have it wrapped correctly.

#### all[¶](#all "Permalink to this heading")

This method selects all first level of depth layout objects:

```

form.helper.all().wrap(Field, css\_class="hello")

```

#### Selecting a field name[¶](#selecting-a-field-name "Permalink to this heading")

If you pass a string with the field name, this field name will be searched greedy throughout the whole Layout depth levels. Imagine we have this layout:

```

Layout(

    'field\_1',

    Div(

        Div('password')

    ),

    'field\_3'

)

```

If we do:

```

form.helper['password'].wrap(Field, css\_class="hero")

```

Previous layout would become:

```

Layout(

    'field\_1',

    Div(

        Div(

            Field('password', css\_class="hero")

        )

    ),

    'field\_3'

)

```

#### filter[¶](#filter "Permalink to this heading")

This method will allow you to filter layout objects by its class type, applying actions to them:

```

form.helper.filter(basestring).wrap(Field, css\_class="hello")

form.helper.filter(Div).wrap(Field, css\_class="hello")

```

You can filter several layout objects types at the same time:

```

form.helper.filter(basestring, Div).wrap(Div, css\_class="hello")

```

By default `filter` is not greedy, so it only searches first depth level. But you can tune it to search in different levels of depth with a kwarg `max\_level` (By default set to 0). Let’ see some examples, to clarify it. Imagine we have this layout:

```

Layout(

    'field\_1',

    Div(

        Div('password')

    ),

    'field\_3'

)

```

If we did:

```

form.helper.filter(basestring).wrap(Field, css\_class="hello")

```

Only `field\_1` and `field\_3` would be wrapped, resulting into:

```

Layout(

    Field('field\_1', css\_class="hello"),

    Div(

        Div('password')

    ),

    Field('field\_3', css\_class="hello"),

)

```

If we wanted to search deeper, wrapping `password`, we would need to set `max\_level` to 2 or more:

```

form.helper.filter(basestring, max\_level=2).wrap(Field, css\_class="hello")

```

In other words `max\_level` indicates the number of jumps crispy-forms can do within a layout object for matching. In this case getting into the first `Div` would be one jump, and getting into the next `Div` would be the second jump, thus `max\_level=2`.

We can turn filter greedy, making it search as deep as possible, setting `greedy` to `True`:

```

form.helper.filter(basestring, greedy=True).wrap(Div, css\_class="hello")

```

**Parameters:**

> 

> * `max\_level`: An integer representing the number of jumps that crispy-forms should do when filtering. Defaults to `0`.

> * `greedy`: A boolean that indicates whether to filter greedy or not. Defaults to `False`.

> 

> 

> 

#### filter\_by\_widget[¶](#filter-by-widget "Permalink to this heading")

Matches all fields of a widget type. This method assumes you are using a helper with a form attached, see section [FormHelper with a form attached (Default layout)](index.html#helper-form-attached), you could filter by widget type doing:

```

form.helper.filter\_by\_widget(forms.PasswordInput).wrap(Field, css\_class="hero")

```

`filter\_by\_widget` is greedy by default, so it searches in depth. Let’s see a use case example, imagine we have this Layout:

```

Layout(

    'username',

    Div('password1'),

    Div('password2')

)

```

Supposing `password1` and `password2` fields are using widget `PasswordInput`, would turn into:

```

Layout(

    'username',

    Div(Field('password1', css\_class="hero")),

    Div(Field('password2', css\_class="hero"))

)

```

An interesting real use case example here would be to wrap all `SelectInputs` with a custom made `ChosenField` that renders the field using a chosenjs compatible field.

#### exclude\_by\_widget[¶](#exclude-by-widget "Permalink to this heading")

Excludes all fields of a widget type. This method assumes you are using a helper with a form attached, see section [FormHelper with a form attached (Default layout)](index.html#helper-form-attached):

```

form.helper.exclude\_by\_widget(forms.PasswordInput).wrap(Field, css\_class="hero")

```

`exclude\_by\_widget` is greedy by default, so it searches in depth. Let’s see a use case example, imagine we have this Layout:

```

Layout(

    'username',

    Div('password1'),

    Div('password2')

)

```

Supposing `password1` and `password2` fields are using widget `PasswordInput`, would turn into:

```

Layout(

    Field('username', css\_class="hero"),

    Div('password1'),

    Div('password2')

)

```

#### Manipulating a layout[¶](#manipulating-a-layout "Permalink to this heading")

Besides selecting layout objects and applying actions to them, you can also manipulate layouts themselves and layout objects easily, like if they were lists. We won’t do this from the helper, but the layout and layout objects themselves. Consider this a lower level API.

All layout objects that can wrap others, contain a inner attribute `fields` which is a list, not a dictionary as in Django forms. You can apply any list methods on them easily. Beware that a `Layout` behaves itself like other layout objects such as `Div`, the only difference is that it is the root of the tree.

This is how you would replace a layout object for other:

```

layout[0][3][1] = Div('field\_1')

```

This is how you would add one layout object at the end of the Layout:

```

layout.append(HTML("<p>whatever</p>"))

```

This is how you would add one layout object at the end of another layout object:

```

layout[0].append(HTML("<p>whatever</p>"))

```

This is how you would add several layout objects to a Layout:

```

layout.extend([

    HTML("<p>whatever</p>"),

    Div('add\_field\_on\_the\_go')

])

```

This is how you would add several layout objects to another layout object:

```

layout[0][2].extend([

    HTML("<p>whatever</p>"),

    Div('add\_field\_on\_the\_go')

])

```

This is how you would delete the second layout object within the Layout:

```

layout.pop(1)

```

This is how you wold delete the second layout object within the second layout object:

```

layout[1].pop(1)

```

This is how you would insert a layout object in the second position of a Layout:

```

layout.insert(1, HTML("<p>whatever</p>"))

```

This is how you would insert a layout object in the second position of the second layout object:

```

layout[1].insert(1, HTML("<p>whatever</p>"))

```

Warning

Remember always that if you are going to manipulate a helper or layout in a view or any part of your code, you better use an instance level variable.

### Frequently Asked Questions[¶](#frequently-asked-questions "Permalink to this heading")

* [Technical](#technical)

	+ [Displaying columns in a bootstrap Layout](#displaying-columns-in-a-bootstrap-layout)

	+ [Using a custom widget](#using-a-custom-widget)

* [General](#general)

	+ [Why use django-crispy-forms and not other app](#why-use-django-crispy-forms-and-not-other-app)

	+ [How did this all get started?](#how-did-this-all-get-started)

	+ [How fast is django-crispy-forms](#how-fast-is-django-crispy-forms)

	+ [Which versions of Python does this support?](#which-versions-of-python-does-this-support)

	+ [Which versions of Django does this support?](#which-versions-of-django-does-this-support)

#### [Technical](#id1)[¶](#technical "Permalink to this heading")

##### [Displaying columns in a bootstrap Layout](#id2)[¶](#displaying-columns-in-a-bootstrap-layout "Permalink to this heading")

Of course you can display form fields within columns, the same way you would do it in a standard bootstrap form, you can do it in a bootstrap layout, see an [example](http://stackoverflow.com/questions/12144475/displaying-multiple-rows-and-columns-in-django-crispy-forms).

##### [Using a custom widget](#id3)[¶](#using-a-custom-widget "Permalink to this heading")

If you are using a custom widget you may find that django-crispy-forms does not render it correctly. In this case please use a custom template for that field, see [Overriding layout objects templates](index.html#override-templates).

#### [General](#id4)[¶](#general "Permalink to this heading")

##### [Why use django-crispy-forms and not other app](#id5)[¶](#why-use-django-crispy-forms-and-not-other-app "Permalink to this heading")

Well, I’m obviously biased for answering this question. But I once [answered it at StackOverflow](http://stackoverflow.com/questions/11749860/how-to-render-django-forms-choicefield-as-twitter-bootstrap-dropdown).

##### [How did this all get started?](#id6)[¶](#how-did-this-all-get-started "Permalink to this heading")

In December 2008, while [Daniel Feldroy](https://twitter.com/pydanny) was working for [NASA’s Science Mission Directorate](https://science.nasa.gov), his team began to use [Django](https://djangoproject.com) and [Pinax](https://pinaxproject.com). There was a necessity to make all the forms in Pinax [Section 508](https://en.wikipedia.org/wiki/Section_508) compatible, and the thought of going through all of forms and rewriting `{{ form }}` as a block of `{% for field in form %}` with all the template logic seemed like way too much work.

So with the encouragement of [Katie Cunningham](https://twitter.com/kcunning), [James Tauber](https://jtauber.com) and [Jannis Leidel](https://twitter.com/jezdez) Daniel took the Django docs on forms and combined it with Dragan Babic’s excellent Uni-Form CSS/JavaScript library and created the ubiquitous `as\_uni\_form` filter. After that, fixing all the forms in Pinax to be section 508 compliant was trivial.

Not long before PyCon 2009 James Tauber suggested the `{% uni\_form form helper %}` API, where one could trivially create forms without writing any HTML.

At PyCon 2009 Jannis Leidel helped Daniel through releasing the 0.3 release of django-uni-form on PyPI. It was also at that PyCon when the project moved from Google Code to Github.

Around January 2011 the project wasn’t very active, Github issues and forks were stacking up. At that time [Miguel Araujo](https://twitter.com/maraujop) found django-uni-form and loved the concept behind its architecture. He started working in a fork of the project, trying to gather some old submitted patches. Around march of 2011, after conversations with Daniel, he got commit powers in the project’s repository, reactivating dev branch. Releases 0.8.0, 0.9.0 followed and the project more than doubled its watchers in Github.

By the end of 2011, Miguel and Daniel agreed on the necessity of renaming the project. As uni-form CSS framework was not anymore the only option available and the name was confusing the users. Thus django-crispy-forms was born, named by [Audrey Feldroy](https://twitter.com/audreyfeldroy). The project is now actively maintained and leaded by [Miguel Araujo](https://twitter.com/maraujop).

##### [How fast is django-crispy-forms](#id7)[¶](#how-fast-is-django-crispy-forms "Permalink to this heading")

Performance in form rendering is normally a nigh moot issue in Django, because the majority of speed issues are fixable via appropriate use of Django’s cache engine. Templates and especially form rendering are usually the last things to worry about when you try to increase performance.

However, because we do care about producing lean and fast code, work is being done to speed up and measure performance of this library. These are the average times of rendering 1000 forms with the latest django-crispy-forms code in Dell Latitude E6500 Intel Core 2 Duo @ 2.53GHz.

In production environments, you will want to activate template caching, see [Installing django-crispy-forms](index.html#install).

| Method | Time with template caching |

| --- | --- |

| Plain Django | 0.915469169617 sec |

| `|crispy` filter | 4.23220916295 sec |

| `{% crispy %}` tag | 4.53284406662 sec |

##### [Which versions of Python does this support?](#id8)[¶](#which-versions-of-python-does-this-support "Permalink to this heading")

Versions supported include Python 2.6.x, 2.7.x, Python 3.3.x. If you need greater backwards compatibility, django-crispy-forms below 1.3 supports 2.5.x, and django-uni-form 0.7.0 supports Python 2.4.x.

##### [Which versions of Django does this support?](#id9)[¶](#which-versions-of-django-does-this-support "Permalink to this heading")

Versions supported include Django 1.3 or higher. Versions of django-crispy-forms below 1.3 support Django 1.2.x. If you need to support earlier versions you will need to use django-uni-form 0.7.0.

* See who’s contributed to the project at [crispy-forms contributors](https://github.com/django-crispy-forms/django-crispy-forms/blob/main/CONTRIBUTORS.txt)

* You can find a detailed history of the project in [Github’s CHANGELOG](https://github.com/django-crispy-forms/django-crispy-forms/blob/main/CHANGELOG.md)

API documentation[¶](#api-documentation "Permalink to this heading")

--------------------------------------------------------------------

If you are looking for information on a specific function, class or method, this part of the documentation is for you.

### API helpers[¶](#module-helper "Permalink to this heading")

*class* helper.FormHelper(*form=None*)[[source]](_modules/helper.html#FormHelper)[¶](#helper.FormHelper "Permalink to this definition")

This class controls the form rendering behavior of the form passed to

the {% crispy %} tag. For doing so you will need to set its attributes

and pass the corresponding helper object to the tag:

```

{% crispy form form.helper %}

```

Let’s see what attributes you can set and what form behaviors they apply to:

> 

> 

> **form\_method**: Specifies form method attribute.You can set it to ‘POST’ or ‘GET’. Defaults to ‘POST’

> 

> 

> 

> **form\_action**: Applied to the form action attribute:* Can be a named url in your URLconf that can be executed via the {% url %} template tag. Example: ‘show\_my\_profile’. In your URLconf you could have something like:

> 

> 

> 

> ```

> path('show/profile/', 'show\_my\_profile\_view', name = 'show\_my\_profile')

> 

> ```

> * It can simply point to a URL ‘/whatever/blabla/’.

> 

> 

> 

> **form\_id**: Generates a form id for dom identification.If no id provided then no id attribute is created on the form.

> 

> 

> 

> **form\_class**: String containing separated CSS classes to be appliedto form class attribute.

> 

> 

> 

> **form\_group\_wrapper\_class**: String containing separated CSS classes to be appliedto each row of inputs.

> 

> 

> 

> **form\_tag**: It specifies if <form></form> tags should be rendered when using a Layout.If set to False it renders the form without the <form></form> tags. Defaults to True.

> 

> 

> 

> **form\_error\_title**: If a form has non\_field\_errors to display, theyare rendered in a div. You can set title’s div with this attribute.

> Example: “Oooops!” or “Form Errors”

> 

> 

> 

> **formset\_error\_title**: If a formset has non\_form\_errors to display, theyare rendered in a div. You can set title’s div with this attribute.

> 

> 

> 

> **include\_media**: Whether to automatically include form media. Set to False ifyou want to manually include form media outside the form. Defaults to True.

> 

> 

> 

> 

> 

Public Methods:

> 

> 

> **add\_input(input)**: You can add input buttons using this method. Inputsadded using this method will be rendered at the end of the form/formset.

> 

> 

> 

> **add\_layout(layout)**: You can add a Layout object to FormHelper. The Layoutspecifies in a simple, clean and DRY way how the form fields should be rendered.

> You can wrap fields, order them, customize pretty much anything in the form.

> 

> 

> 

> 

> 

Best way to add a helper to a form is adding a property named helper to the form

that returns customized FormHelper object:

```

from crispy\_forms.helper import FormHelper

from crispy\_forms.layout import Submit

class MyForm(forms.Form):

    title = forms.CharField(\_("Title"))

    @property

    def helper(self):

        helper = FormHelper()

        helper.form\_id = 'this-form-rocks'

        helper.form\_class = 'search'

        helper.add\_input(Submit('save', 'save'))

        [...]

        return helper

```

You can use it in a template doing:

```

{% load crispy\_forms\_tags %}

{% crispy form %}

```

get\_attributes(*template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*)[[source]](_modules/helper.html#FormHelper.get_attributes)[¶](#helper.FormHelper.get_attributes "Permalink to this definition")

Used by crispy\_forms\_tags to get helper attributes

render\_layout(*form*, *context*, *template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*)[[source]](_modules/helper.html#FormHelper.render_layout)[¶](#helper.FormHelper.render_layout "Permalink to this definition")

Returns safe html of the rendering of the layout

### API Layout[¶](#module-layout "Permalink to this heading")

*class* layout.BaseInput(*name*, *value*, *\**, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#BaseInput)[¶](#layout.BaseInput "Permalink to this definition")

A base class to reduce the amount of code in the Input classes.

Parameters

**name**strThe name attribute of the button.

**value**strThe value attribute of the button.

**css\_id**str, optionalA custom DOM id for the layout object. If not provided the name

argument is slugified and turned into the id for the submit button.

By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to flatatt and converted into

key=”value”, pairs. These attributes are added to the `<input>`.

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**field\_classes: str**CSS classes to be applied to the `<input>`.

render(*form*, *context*, *template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*, *\*\*kwargs*)[[source]](_modules/layout.html#BaseInput.render)[¶](#layout.BaseInput.render "Permalink to this definition")

Renders an <input /> if container is used as a Layout object.

Input button value can be a variable in context.

*class* layout.Button(*name*, *value*, *\**, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Button)[¶](#layout.Button "Permalink to this definition")

Used to create a button descriptor for the {% crispy %} template tag.

Parameters

**name**strThe name attribute of the button.

**value**strThe value attribute of the button.

**css\_id**str, optionalA custom DOM id for the layout object. If not provided the name

argument is slugified and turned into the id for the submit button.

By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to flatatt and converted into

key=”value”, pairs. These attributes are added to the `<input>`.

Examples

Note: `form` arg to `render()` is not required for `BaseInput`

inherited objects.

```

>>> button = Button('Button 1', 'Press Me!')

>>> button.render("", "", Context())

'<input type="button" name="button-1" value="Press Me!" '

'class="btn" id="button-id-button-1"/>'

```

```

>>> button = Button('Button 1', 'Press Me!', css\_id="custom-id",

 css\_class="custom class", my\_attr=True, data="my-data")

>>> button.render("", "", Context())

'<input type="button" name="button-1" value="Press Me!" '

'class="btn custom class" id="custom-id" data="my-data" my-attr/>'

```

Usually you will not call the render method on the object directly. Instead

add it to your `Layout` manually or use the add\_input method:

```

class ExampleForm(forms.Form):

[...]

def \_\_init\_\_(self, \*args, \*\*kwargs):

    super().\_\_init\_\_(\*args, \*\*kwargs)

    self.helper = FormHelper()

    self.helper.add\_input(Button('Button 1', 'Press Me!'))

```

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**field\_classes: str**CSS classes to be applied to the `<input>`.

**input\_type: str**The `type` attribute of the `<input>`.

*class* layout.ButtonHolder(*\*fields*, *css\_id=None*, *css\_class=None*, *template=None*)[[source]](_modules/layout.html#ButtonHolder)[¶](#layout.ButtonHolder "Permalink to this definition")

Layout object. It wraps fields in a <div class=”buttonHolder”>

This is where you should put Layout objects that render to form buttons

Parameters

**\*fields**HTML or BaseInputThe layout objects to render within the `ButtonHolder`. It should

only hold HTML and BaseInput inherited objects.

**css\_id**str, optionalA custom DOM id for the layout object. If not provided the name

argument is slugified and turned into the id for the submit button.

By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

Examples

An example using `ButtonHolder` in your layout:

```

ButtonHolder(

    HTML(<span style="display: hidden;">Information Saved</span>),

    Submit('Save', 'Save')

)

```

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

*class* layout.Column(*\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Column)[¶](#layout.Column "Permalink to this definition")

Layout object. It wraps fields in a `<div>` and the template adds the

appropriate class to render the contents in a column. e.g. `col-md` when

using the Bootstrap4 template pack.

Parameters

**\*fields**str, LayoutObjectAny number of fields as positional arguments to be rendered within

the `<div>`.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. If using the Bootstrap4 template pack the default

`col-md` is removed if this string contins another `col-` class.

By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

In your `Layout` you can:

```

Column('form\_field\_1', 'form\_field\_2', css\_id='col-example')

```

It is also possible to nest Layout Objects within a Row:

```

Div(

    Column(

        Field('form\_field', css\_class='field-class'),

        css\_class='col-sm,

    ),

    Column('form\_field\_2', css\_class='col-sm'),

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default None.

*class* layout.Div(*\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Div)[¶](#layout.Div "Permalink to this definition")

Layout object. It wraps fields in a `<div>`.

Parameters

**\*fields**str, LayoutObjectAny number of fields as positional arguments to be rendered within

the `<div>`.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

In your `Layout` you can:

```

Div(

    'form\_field\_1',

    'form\_field\_2',

    css\_id='div-example',

    css\_class='divs',

)

```

It is also possible to nest Layout Objects within a Div:

```

Div(

    Div(

        Field('form\_field', css\_class='field-class'),

        css\_class='div-class',

    ),

    Div('form\_field\_2', css\_class='div-class'),

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default None.

*class* layout.Field(*\*fields*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Field)[¶](#layout.Field "Permalink to this definition")

A Layout object, usually containing one field name, where you can add

attributes to it easily.

Parameters

**\*fields**strUsually a single field, but can be any number of fields, to be rendered

with the same attributes applied.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

Field('field\_name', style="color: #333;", css\_class="whatever", id="field\_name")

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

*class* layout.Fieldset(*legend*, *\*fields*, *css\_class=None*, *css\_id=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Fieldset)[¶](#layout.Fieldset "Permalink to this definition")

A layout object which wraps fields in a `<fieldset>`

Parameters

**legend**strThe content of the fieldset’s `<legend>`. This text is context

aware, to bring this to life see the examples section.

**\*fields**strAny number of fields as positional arguments to be rendered within

the `<fieldset>`

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**css\_id**str, optionalA custom DOM id for the layout object. If not provided the name

argument is slugified and turned into the id for the submit button.

By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<fieldset>`.

Examples

The Fieldset Layout object is added to your `Layout` for example:

```

Fieldset("Text for the legend",

    "form\_field\_1",

    "form\_field\_2",

    css\_id="my-fieldset-id",

    css\_class="my-fieldset-class",

    data="my-data"

)

```

The above layout will be rendered as:

```

'''

<fieldset id="fieldset-id" class="my-fieldset-class" data="my-data">

 <legend>Text for the legend</legend>

 # form fields render here

</fieldset>

'''

```

The first parameter is the text for the fieldset legend. This text is context aware,

so you can do things like:

```

Fieldset("Data for {{ user.username }}",

    'form\_field\_1',

    'form\_field\_2'

)

```

*class* layout.HTML(*html*)[[source]](_modules/layout.html#HTML)[¶](#layout.HTML "Permalink to this definition")

Layout object. It can contain pure HTML and it has access to the whole

context of the page where the form is being rendered.

Examples:

```

HTML("{% if saved %}Data saved{% endif %}")

HTML('<input type="hidden" name="{{ step\_field }}" value="{{ step0 }}" />')

```

*class* layout.Hidden(*name*, *value*, *\**, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Hidden)[¶](#layout.Hidden "Permalink to this definition")

Used to create a Hidden input descriptor for the {% crispy %} template tag.

Parameters

**name**strThe name attribute of the button.

**value**strThe value attribute of the button.

**css\_id**str, optionalA custom DOM id for the layout object. If not provided the name

argument is slugified and turned into the id for the submit button.

By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to flatatt and converted into

key=”value”, pairs. These attributes are added to the `<input>`.

Examples

Note: `form` arg to `render()` is not required for `BaseInput`

inherited objects.

```

>>> hidden = Hidden("hidden", "hide-me")

>>> hidden.render("", "", Context())

'<input type="hidden" name="hidden" value="hide-me"/>'

```

Usually you will not call the render method on the object directly. Instead

add it to your `Layout` manually or use the add\_input method:

```

class ExampleForm(forms.Form):

[...]

def \_\_init\_\_(self, \*args, \*\*kwargs):

    super().\_\_init\_\_(\*args, \*\*kwargs)

    self.helper = FormHelper()

    self.helper.add\_input(Hidden("hidden", "hide-me"))

```

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**field\_classes: str**CSS classes to be applied to the `<input>`.

**input\_type: str**The `type` attribute of the `<input>`.

*class* layout.Layout(*\*fields*)[[source]](_modules/layout.html#Layout)[¶](#layout.Layout "Permalink to this definition")

Form Layout. It is conformed by Layout objects: Fieldset, Row, Column, MultiField,

HTML, ButtonHolder, Button, Hidden, Reset, Submit and fields. Form fields

have to be strings.

Layout objects Fieldset, Row, Column, MultiField and ButtonHolder can hold other

Layout objects within. Though ButtonHolder should only hold HTML and BaseInput

inherited classes: Button, Hidden, Reset and Submit.

Example:

```

helper.layout = Layout(

    Fieldset('Company data',

        'is\_company'

    ),

    Fieldset(\_('Contact details'),

        'email',

        Row('password1', 'password2'),

        'first\_name',

        'last\_name',

        HTML('<img src="/media/somepicture.jpg"/>'),

        'company'

    ),

    ButtonHolder(

        Submit('Save', 'Save', css\_class='button white'),

    ),

)

```

*class* layout.MultiField(*label*, *\*fields*, *label\_class=None*, *help\_text=None*, *css\_class=None*, *css\_id=None*, *template=None*, *field\_template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#MultiField)[¶](#layout.MultiField "Permalink to this definition")

MultiField container for Bootstrap3. Renders to a MultiField <div>.

Parameters

**label: str**The label for the multifield.

**\*fields: str**The fields to be rendered within the multifield.

**label\_class: str, optional**CSS classes to be added to the multifield label. By default None.

**help\_text: str, optional**Help text will be available in the context of the multifield template.

This is unused in the bootstrap3 template provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**css\_id**str, optionalA DOM id for the layout object which will be added to the wrapping

`<div>` if provided. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**field\_template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the wrapping

`<div>`.

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**field\_template: str**The template which fields will be rendered with.

*class* layout.MultiWidgetField(*\*fields*, *attrs=None*, *template=None*, *wrapper\_class=None*)[[source]](_modules/layout.html#MultiWidgetField)[¶](#layout.MultiWidgetField "Permalink to this definition")

Layout object. For fields with `MultiWidget` as

`widget`, you can pass additional attributes to each widget.

Parameters

**\*fields**strUsually a single field, but can be any number of fields, to be rendered

with the same attributes applied.

**attrs**str, optionalAdditional attrs to be added to each widget. These are added to any

classes included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

Examples

Example:

```

MultiWidgetField(

    'multiwidget\_field\_name',

    attrs=(

        {'style': 'width: 30px;'},

        {'class': 'second\_widget\_class'}

    ),

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

*class* layout.Pointer(*positions: List[int]*, *name: str*)[[source]](_modules/layout.html#Pointer)[¶](#layout.Pointer "Permalink to this definition")

*class* layout.Reset(*name*, *value*, *\**, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Reset)[¶](#layout.Reset "Permalink to this definition")

Used to create a reset button descriptor for the {% crispy %} template tag.

Parameters

**name**strThe name attribute of the button.

**value**strThe value attribute of the button.

**css\_id**str, optionalA custom DOM id for the layout object. If not provided the name

argument is slugified and turned into the id for the submit button.

By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to flatatt and converted into

key=”value”, pairs. These attributes are added to the `<input>`.

Examples

Note: `form` arg to `render()` is not required for `BaseInput`

inherited objects.

```

>>> reset = Reset('Reset This Form', 'Revert Me!')

>>> reset.render("", "", Context())

'<input type="reset" name="reset-this-form" value="Revert Me!" '

'class="btn btn-inverse" id="reset-id-reset-this-form"/>'

```

```

>>> reset = Reset('Reset This Form', 'Revert Me!', css\_id="custom-id",

 css\_class="custom class", my\_attr=True, data="my-data")

>>> reset.render("", "", Context())

'<input type="reset" name="reset-this-form" value="Revert Me!" '

'class="btn btn-inverse custom class" id="custom-id" data="my-data" my-attr/>'

```

Usually you will not call the render method on the object directly. Instead

add it to your `Layout` manually manually or use the add\_input method:

```

class ExampleForm(forms.Form):

[...]

def \_\_init\_\_(self, \*args, \*\*kwargs):

    super().\_\_init\_\_(\*args, \*\*kwargs)

    self.helper = FormHelper()

    self.helper.add\_input(Reset('Reset This Form', 'Revert Me!'))

```

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**field\_classes: str**CSS classes to be applied to the `<input>`.

**input\_type: str**The `type` attribute of the `<input>`.

*class* layout.Row(*\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Row)[¶](#layout.Row "Permalink to this definition")

Layout object. It wraps fields in a `<div>` and the template adds the

appropriate class to render the contents in a row. e.g. `form-row` when

using the Bootstrap4 template pack.

Parameters

**\*fields**str, LayoutObjectAny number of fields as positional arguments to be rendered within

the `<div>`.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

In your `Layout` you can:

```

Row('form\_field\_1', 'form\_field\_2', css\_id='row-example')

```

It is also possible to nest Layout Objects within a Row:

```

Row(

    Div(

        Field('form\_field', css\_class='field-class'),

        css\_class='div-class',

    ),

    Div('form\_field\_2', css\_class='div-class'),

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default None.

*class* layout.Submit(*name*, *value*, *\**, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/layout.html#Submit)[¶](#layout.Submit "Permalink to this definition")

Used to create a Submit button descriptor for the {% crispy %} template tag.

Parameters

**name**strThe name attribute of the button.

**value**strThe value attribute of the button.

**css\_id**str, optionalA custom DOM id for the layout object. If not provided the name

argument is slugified and turned into the id for the submit button.

By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<input>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to flatatt and converted into

key=”value”, pairs. These attributes are added to the `<input>`.

Examples

Note: `form` arg to `render()` is not required for `BaseInput`

inherited objects.

```

>>> submit = Submit('Search the Site', 'search this site')

>>> submit.render("", "", Context())

'<input type="submit" name="search-the-site" value="search this site" '

'class="btn btn-primary" id="submit-id-search-the-site"/>'

```

```

>>> submit = Submit('Search the Site', 'search this site', css\_id="custom-id",

 css\_class="custom class", my\_attr=True, data="my-data")

>>> submit.render("", "", Context())

'<input type="submit" name="search-the-site" value="search this site" '

'class="btn btn-primary custom class" id="custom-id" data="my-data" my-attr/>'

```

Usually you will not call the render method on the object directly. Instead

add it to your `Layout` manually or use the add\_input method:

```

class ExampleForm(forms.Form):

[...]

def \_\_init\_\_(self, \*args, \*\*kwargs):

    super().\_\_init\_\_(\*args, \*\*kwargs)

    self.helper = FormHelper()

    self.helper.add\_input(Submit('submit', 'Submit'))

```

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**field\_classes: str**CSS classes to be applied to the `<input>`.

**input\_type: str**The `type` attribute of the `<input>`.

### API templatetags[¶](#module-templatetags.crispy_forms_tags "Permalink to this heading")

*class* templatetags.crispy\_forms\_tags.BasicNode(*form*, *helper*, *template\_pack=None*)[[source]](_modules/templatetags/crispy_forms_tags.html#BasicNode)[¶](#templatetags.crispy_forms_tags.BasicNode "Permalink to this definition")

Basic Node object that we can rely on for Node objects in normal

template tags. I created this because most of the tags we’ll be using

will need both the form object and the helper string. This handles

both the form object and parses out the helper string into attributes

that templates can easily handle.

get\_render(*context*)[[source]](_modules/templatetags/crispy_forms_tags.html#BasicNode.get_render)[¶](#templatetags.crispy_forms_tags.BasicNode.get_render "Permalink to this definition")

Returns a Context object with all the necessary stuff for rendering the form

Parameters

**context** – django.template.Context variable holding the context for the node

self.form and self.helper are resolved into real Python objects resolving them

from the context. The actual\_form can be a form or a formset. If it’s a formset

is\_formset is set to True. If the helper has a layout we use it, for rendering the

form or the formset’s forms.

get\_response\_dict(*helper*, *context*, *is\_formset*)[[source]](_modules/templatetags/crispy_forms_tags.html#BasicNode.get_response_dict)[¶](#templatetags.crispy_forms_tags.BasicNode.get_response_dict "Permalink to this definition")

Returns a dictionary with all the parameters necessary to render the form/formset in a template.

Parameters

* **context** – django.template.Context for the node

* **is\_formset** – Boolean value. If set to True, indicates we are working with a formset.

*class* templatetags.crispy\_forms\_tags.CrispyFormNode(*form*, *helper*, *template\_pack=None*)[[source]](_modules/templatetags/crispy_forms_tags.html#CrispyFormNode)[¶](#templatetags.crispy_forms_tags.CrispyFormNode "Permalink to this definition")

render(*context*)[[source]](_modules/templatetags/crispy_forms_tags.html#CrispyFormNode.render)[¶](#templatetags.crispy_forms_tags.CrispyFormNode.render "Permalink to this definition")

Return the node rendered as a string.

*class* templatetags.crispy\_forms\_tags.ForLoopSimulator(*formset*)[[source]](_modules/templatetags/crispy_forms_tags.html#ForLoopSimulator)[¶](#templatetags.crispy_forms_tags.ForLoopSimulator "Permalink to this definition")

Simulates a forloop tag, precisely:

```

{% for form in formset.forms %}

```

If {% crispy %} is rendering a formset with a helper, We inject a ForLoopSimulator object

in the context as forloop so that formset forms can do things like:

```

Fieldset("Item {{ forloop.counter }}", [...])

HTML("{% if forloop.first %}First form text{% endif %}"

```

iterate()[[source]](_modules/templatetags/crispy_forms_tags.html#ForLoopSimulator.iterate)[¶](#templatetags.crispy_forms_tags.ForLoopSimulator.iterate "Permalink to this definition")

Updates values as if we had iterated over the for

templatetags.crispy\_forms\_tags.do\_uni\_form(*parser*, *token*)[[source]](_modules/templatetags/crispy_forms_tags.html#do_uni_form)[¶](#templatetags.crispy_forms_tags.do_uni_form "Permalink to this definition")

You need to pass in at least the form/formset object, and can also pass in the

optional crispy\_forms.helpers.FormHelper object.

helper (optional): A crispy\_forms.helper.FormHelper object.

Usage:

```

{% load crispy\_tags %}

{% crispy form form.helper %}

```

You can also provide the template pack as the third argument:

```

{% crispy form form.helper 'bootstrap' %}

```

If the FormHelper attribute is named helper you can simply do:

```

{% crispy form %}

{% crispy form 'bootstrap' %}

```

templatetags.crispy\_forms\_tags.whole\_uni\_form\_template(*template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*)[[source]](_modules/templatetags/crispy_forms_tags.html#whole_uni_form_template)[¶](#templatetags.crispy_forms_tags.whole_uni_form_template "Permalink to this definition")

templatetags.crispy\_forms\_tags.whole\_uni\_formset\_template(*template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*)[[source]](_modules/templatetags/crispy_forms_tags.html#whole_uni_formset_template)[¶](#templatetags.crispy_forms_tags.whole_uni_formset_template "Permalink to this definition")

templatetags.crispy\_forms\_filters.as\_crispy\_errors(*form*, *template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*)[[source]](_modules/templatetags/crispy_forms_filters.html#as_crispy_errors)[¶](#templatetags.crispy_forms_filters.as_crispy_errors "Permalink to this definition")

Renders only form errors the same way as django-crispy-forms:

```

{% load crispy\_forms\_tags %}

{{ form|as\_crispy\_errors }}

```

or:

```

{{ form|as\_crispy\_errors:"bootstrap4" }}

```

templatetags.crispy\_forms\_filters.as\_crispy\_field(*field*, *template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*, *label\_class=''*, *field\_class=''*)[[source]](_modules/templatetags/crispy_forms_filters.html#as_crispy_field)[¶](#templatetags.crispy_forms_filters.as_crispy_field "Permalink to this definition")

Renders a form field like a django-crispy-forms field:

```

{% load crispy\_forms\_tags %}

{{ form.field|as\_crispy\_field }}

```

or:

```

{{ form.field|as\_crispy\_field:"bootstrap4" }}

```

templatetags.crispy\_forms\_filters.as\_crispy\_form(*form*, *template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*, *label\_class=''*, *field\_class=''*)[[source]](_modules/templatetags/crispy_forms_filters.html#as_crispy_form)[¶](#templatetags.crispy_forms_filters.as_crispy_form "Permalink to this definition")

The original and still very useful way to generate a div elegant form/formset:

```

{% load crispy\_forms\_tags %}

<form class="my-class" method="post">

    {% csrf\_token %}

    {{ myform|crispy }}

</form>

```

or, if you want to explicitly set the template pack:

```

{{ myform|crispy:"bootstrap4" }}

```

In `bootstrap3` or `bootstrap4` for horizontal forms you can do:

```

{{ myform|label\_class:"col-lg-2",field\_class:"col-lg-8" }}

```

templatetags.crispy\_forms\_filters.flatatt\_filter(*attrs*)[[source]](_modules/templatetags/crispy_forms_filters.html#flatatt_filter)[¶](#templatetags.crispy_forms_filters.flatatt_filter "Permalink to this definition")

templatetags.crispy\_forms\_filters.optgroups(*field*)[[source]](_modules/templatetags/crispy_forms_filters.html#optgroups)[¶](#templatetags.crispy_forms_filters.optgroups "Permalink to this definition")

A template filter to help rendering of fields with optgroups.

Returns:A tuple of label, option, index

label: Group label for grouped optgroups (None if inputs are notgrouped).

option: A dict containing information to render the option:

```

{

    "name": "checkbox\_select\_multiple",

    "value": 1,

    "label": 1,

    "selected": False,

    "index": "0",

    "attrs": {"id": "id\_checkbox\_select\_multiple\_0"},

    "type": "checkbox",

    "template\_name": "django/forms/widgets/checkbox\_option.html",

    "wrap\_label": True,

}

```

index: Group index

templatetags.crispy\_forms\_filters.uni\_form\_template(*template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*)[[source]](_modules/templatetags/crispy_forms_filters.html#uni_form_template)[¶](#templatetags.crispy_forms_filters.uni_form_template "Permalink to this definition")

templatetags.crispy\_forms\_filters.uni\_formset\_template(*template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*)[[source]](_modules/templatetags/crispy_forms_filters.html#uni_formset_template)[¶](#templatetags.crispy_forms_filters.uni_formset_template "Permalink to this definition")

*class* templatetags.crispy\_forms\_field.CrispyFieldNode(*field*, *attrs*)[[source]](_modules/templatetags/crispy_forms_field.html#CrispyFieldNode)[¶](#templatetags.crispy_forms_field.CrispyFieldNode "Permalink to this definition")

render(*context*)[[source]](_modules/templatetags/crispy_forms_field.html#CrispyFieldNode.render)[¶](#templatetags.crispy_forms_field.CrispyFieldNode.render "Permalink to this definition")

Return the node rendered as a string.

templatetags.crispy\_forms\_field.classes(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#classes)[¶](#templatetags.crispy_forms_field.classes "Permalink to this definition")

Returns CSS classes of a field

templatetags.crispy\_forms\_field.crispy\_addon(*field*, *append=''*, *prepend=''*, *form\_show\_labels=True*)[[source]](_modules/templatetags/crispy_forms_field.html#crispy_addon)[¶](#templatetags.crispy_forms_field.crispy_addon "Permalink to this definition")

Renders a form field using bootstrap’s prepended or appended text:

```

{% crispy\_addon form.my\_field prepend="$" append=".00" %}

```

You can also just prepend or append like so

> 

> {% crispy\_addon form.my\_field prepend=”$” %}

> {% crispy\_addon form.my\_field append=”.00” %}

> 

> 

> 

templatetags.crispy\_forms\_field.crispy\_field(*parser*, *token*)[[source]](_modules/templatetags/crispy_forms_field.html#crispy_field)[¶](#templatetags.crispy_forms_field.crispy_field "Permalink to this definition")

{% crispy\_field field attrs %}

templatetags.crispy\_forms\_field.css\_class(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#css_class)[¶](#templatetags.crispy_forms_field.css_class "Permalink to this definition")

Returns widgets class name in lowercase

templatetags.crispy\_forms\_field.is\_checkbox(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_checkbox)[¶](#templatetags.crispy_forms_field.is_checkbox "Permalink to this definition")

templatetags.crispy\_forms\_field.is\_checkboxselectmultiple(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_checkboxselectmultiple)[¶](#templatetags.crispy_forms_field.is_checkboxselectmultiple "Permalink to this definition")

templatetags.crispy\_forms\_field.is\_clearable\_file(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_clearable_file)[¶](#templatetags.crispy_forms_field.is_clearable_file "Permalink to this definition")

templatetags.crispy\_forms\_field.is\_file(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_file)[¶](#templatetags.crispy_forms_field.is_file "Permalink to this definition")

templatetags.crispy\_forms\_field.is\_multivalue(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_multivalue)[¶](#templatetags.crispy_forms_field.is_multivalue "Permalink to this definition")

templatetags.crispy\_forms\_field.is\_password(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_password)[¶](#templatetags.crispy_forms_field.is_password "Permalink to this definition")

templatetags.crispy\_forms\_field.is\_radioselect(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_radioselect)[¶](#templatetags.crispy_forms_field.is_radioselect "Permalink to this definition")

templatetags.crispy\_forms\_field.is\_select(*field*)[[source]](_modules/templatetags/crispy_forms_field.html#is_select)[¶](#templatetags.crispy_forms_field.is_select "Permalink to this definition")

templatetags.crispy\_forms\_field.pairwise(*iterable*)[[source]](_modules/templatetags/crispy_forms_field.html#pairwise)[¶](#templatetags.crispy_forms_field.pairwise "Permalink to this definition")

s -> (s0,s1), (s2,s3), (s4, s5), …

### API Bootstrap[¶](#module-crispy_forms.bootstrap "Permalink to this heading")

*class* crispy\_forms.bootstrap.Accordion(*\*accordion\_groups*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#Accordion)[¶](#crispy_forms.bootstrap.Accordion "Permalink to this definition")

Accordion menu object. It wraps AccordionGroup objects in a container

Parameters

**\*accordion\_groups**str, LayoutObjectAny number of layout objects as positional arguments to be rendered

within the `<div>`.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

Example:

```

Accordion(

    AccordionGroup("group name", "form\_field\_1", "form\_field\_2"),

    AccordionGroup("another group name", "form\_field")

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default None.

*class* crispy\_forms.bootstrap.AccordionGroup(*name*, *\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *active=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#AccordionGroup)[¶](#crispy_forms.bootstrap.AccordionGroup "Permalink to this definition")

Accordion Group (pane) object. It wraps given fields inside an accordion

tab. It takes accordion tab name as first argument.

Tab object. It wraps fields in a div whose default class is “tab-pane” and

takes a name as first argument.

Parameters

**name**strThe name of the container.

**\*fields**str, LayoutObjectAny number of fields as positional arguments to be rendered within

the container.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

Example:

```

AccordionGroup("group name", "form\_field\_1", "form\_field\_2")

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default “”.

*class* crispy\_forms.bootstrap.Alert(*content*, *dismiss=True*, *block=False*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#Alert)[¶](#crispy_forms.bootstrap.Alert "Permalink to this definition")

Generates markup in the form of an alert dialog.

Parameters

**content**strThe content of the alert.

**dismiss**boolIf true the alert contains a button to dismiss the alert. By default

True.

**block**str, optionalAdditional CSS classes to be applied to the `<button>`. By default

None.

**css\_id**str, optionalA DOM id for the layout object which will be added to the alert if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are then available in the template

context.

Examples

Example:

```

Alert(content='<strong>Warning!</strong> Best check yo self, you're not looking too good.')

```

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**css\_class**strThe CSS classes to be applied to the alert. By defult “alert”.

*class* crispy\_forms.bootstrap.AppendedText(*field*, *text*, *\**, *input\_size=None*, *active=False*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#AppendedText)[¶](#crispy_forms.bootstrap.AppendedText "Permalink to this definition")

Layout object for rendering a field with appended text.

Parameters

**field**strThe name of the field to be rendered.

**text**strThe appended text, can be HTML like.

**input\_size**str, optionalFor Bootstrap4+ additional classes to customise the input-group size

e.g. `input-group-sm`. By default None

**active**boolFor Bootstrap3, a boolean to render the text active. By default

`False`.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

AppendedText('amount', '.00')

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

*class* crispy\_forms.bootstrap.Container(*name*, *\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *active=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#Container)[¶](#crispy_forms.bootstrap.Container "Permalink to this definition")

Base class used for Tab and AccordionGroup, represents a basic

container concept.

Parameters

**name**strThe name of the container.

**\*fields**str, LayoutObjectAny number of fields as positional arguments to be rendered within

the container.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default “”.

*class* crispy\_forms.bootstrap.ContainerHolder(*\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#ContainerHolder)[¶](#crispy_forms.bootstrap.ContainerHolder "Permalink to this definition")

Base class used for TabHolder and Accordion, groups containers.

Parameters

**\*fields**str, LayoutObjectAny number of fields or layout objects as positional arguments to be

rendered within the `<div>`.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default None.

first\_container\_with\_errors(*errors*)[[source]](_modules/crispy_forms/bootstrap.html#ContainerHolder.first_container_with_errors)[¶](#crispy_forms.bootstrap.ContainerHolder.first_container_with_errors "Permalink to this definition")

Returns the first container with errors, otherwise returns None.

open\_target\_group\_for\_form(*form*)[[source]](_modules/crispy_forms/bootstrap.html#ContainerHolder.open_target_group_for_form)[¶](#crispy_forms.bootstrap.ContainerHolder.open_target_group_for_form "Permalink to this definition")

Makes sure that the first group that should be open is open.

This is either the first group with errors or the first group

in the container, unless that first group was originally set to

active=False.

*class* crispy\_forms.bootstrap.FieldWithButtons(*\*fields*, *input\_size=None*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#FieldWithButtons)[¶](#crispy_forms.bootstrap.FieldWithButtons "Permalink to this definition")

A layout object for rendering a single field with any number of buttons.

Parameters

**\*fields**str or LayoutObjectThe first positional argument is the field. This can be either the

name of the field as a string or an instance of Field. Following

arguments will be rendered as buttons.

**input\_size**strAdditional CSS class to change the size of the input. e.g.

“input-group-sm”.

**css\_id**str, optionalA DOM id for the layout object which will be added to the wrapping

`<div>` if provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the wrapping

`<div>`.

Examples

Example:

```

FieldWithButtons(

    Field("password1", css\_class="span4"),

    StrictButton("Go!", css\_id="go-button"),

    input\_size="input-group-sm",

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the wrapping `<div>`. By default None.

*class* crispy\_forms.bootstrap.FormActions(*\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#FormActions)[¶](#crispy_forms.bootstrap.FormActions "Permalink to this definition")

Bootstrap layout object. It wraps fields in a <div class=”form-actions”>

Parameters

**\*fields**HTML or BaseInputThe layout objects to render within the `ButtonHolder`. It should

only hold HTML and BaseInput inherited objects.

**css\_id**str, optionalA custom DOM id for the layout object which will be added to the

`<div>` if provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<div>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

An example using `FormActions` in your layout:

```

FormActions(

    HTML(<span style="display: hidden;">Information Saved</span>),

    Submit('Save', 'Save', css\_class='btn-primary')

)

```

Attributes

**template: str**The default template which this Layout Object will be rendered with.

*class* crispy\_forms.bootstrap.InlineCheckboxes(*\*fields*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#InlineCheckboxes)[¶](#crispy_forms.bootstrap.InlineCheckboxes "Permalink to this definition")

Layout object for rendering checkboxes inline.

Parameters

**\*fields**strUsually a single field, but can be any number of fields, to be rendered

with the same attributes applied.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

InlineCheckboxes('field\_name')

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

*class* crispy\_forms.bootstrap.InlineField(*\*fields*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#InlineField)[¶](#crispy_forms.bootstrap.InlineField "Permalink to this definition")

Layout object for rendering fields as Inline in bootstrap.

Parameters

**\*fields**strUsually a single field, but can be any number of fields, to be rendered

with the same attributes applied.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

InlineField('field\_name')

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

*class* crispy\_forms.bootstrap.InlineRadios(*\*fields*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#InlineRadios)[¶](#crispy_forms.bootstrap.InlineRadios "Permalink to this definition")

Layout object for rendering radiobuttons inline.

Parameters

**\*fields**strUsually a single field, but can be any number of fields, to be rendered

with the same attributes applied.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

InlineRadios('field\_name')

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

*class* crispy\_forms.bootstrap.Modal(*\*fields*, *template=None*, *css\_id='modal\_id'*, *title='Modal Title'*, *title\_id='modal\_title\_id'*, *css\_class=None*, *title\_class=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#Modal)[¶](#crispy_forms.bootstrap.Modal "Permalink to this definition")

Boostrap layout object for rendering crispy forms objects inside a

bootstrap modal.

Parameters

**\*fields**strThe fields to be rendered within the modal.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**css\_id: str, optional**The modal’s DOM id. By default `modal\_id`.

**title: str, optional**Text to display in the modal’s header which will be wrapped in an

`<H5>` tag. By default `Modal Title`.

**title\_id: str, optional**The title’s DOM id. By default `modal\_title\_id`.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default None.

**title\_class: str, optional**Additional CSS classes to be applied to the title. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

Modal(

    'field1',

    Div('field2'),

    css\_id="modal-id-ex",

    css\_class="modal-class-ex,

    title="This is my modal",

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

*class* crispy\_forms.bootstrap.PrependedAppendedText(*field*, *prepended\_text=None*, *appended\_text=None*, *input\_size=None*, *\**, *active=False*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#PrependedAppendedText)[¶](#crispy_forms.bootstrap.PrependedAppendedText "Permalink to this definition")

Layout object for rendering a field with prepended and appended text.

Parameters

**field**strThe name of the field to be rendered.

**prepended\_text**str, optionalThe prepended text, can be HTML like, by default None

**appended\_text**str, optionalThe appended text, can be HTML like, by default None

**input\_size**str, optionalFor Bootstrap4+ additional classes to customise the input-group size

e.g. `input-group-sm`. By default None

**active**boolFor Bootstrap3, a boolean to render the text active. By default

`False`.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

PrependedAppendedText('amount', '$', '.00')

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

*class* crispy\_forms.bootstrap.PrependedText(*field*, *text*, *\**, *input\_size=None*, *active=False*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#PrependedText)[¶](#crispy_forms.bootstrap.PrependedText "Permalink to this definition")

Layout object for rendering a field with prepended text.

Parameters

**field**strThe name of the field to be rendered.

**text**strThe prepended text, can be HTML like.

**input\_size**str, optionalFor Bootstrap4+ additional classes to customise the input-group size

e.g. `input-group-sm`. By default None

**active**boolFor Bootstrap3, a boolean to render the text active. By default

`False`.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

PrependedText('amount', '$')

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

*class* crispy\_forms.bootstrap.StrictButton(*content*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#StrictButton)[¶](#crispy_forms.bootstrap.StrictButton "Permalink to this definition")

Layout object for rendering an HTML button in a `<button>` tag.

Parameters

**content**strThe content of the button. This content is context aware, to bring

this to life see the examples section.

**css\_id**str, optionalA custom DOM id for the layout object which will be added to the

`<button>` if provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied to the `<button>`. By default

None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to flatatt and converted into

key=”value”, pairs. These attributes are added to the `<button>`.

Examples

In your `Layout`:

```

StrictButton("button content", css\_class="extra")

```

The content of the button is context aware, so you can do things like:

```

StrictButton("Button for {{ user.username }}")

```

Attributes

**template: str**The default template which this Layout Object will be rendered

with.

**field\_classes**strThe CSS classes to be applied to the button. By defult “btn”.

*class* crispy\_forms.bootstrap.Tab(*name*, *\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *active=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#Tab)[¶](#crispy_forms.bootstrap.Tab "Permalink to this definition")

Tab object. It wraps fields in a div whose default class is “tab-pane” and

takes a name as first argument.

Parameters

**name**strThe name of the container.

**\*fields**str, LayoutObjectAny number of fields as positional arguments to be rendered within

the container.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

Example:

```

Tab('tab\_name', 'form\_field\_1', 'form\_field\_2', 'form\_field\_3')

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default “”.

render\_link(*template\_pack=<SimpleLazyObject: <function get\_template\_pack>>*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#Tab.render_link)[¶](#crispy_forms.bootstrap.Tab.render_link "Permalink to this definition")

Render the link for the tab-pane. It must be called after render so css\_class is updated

with active if needed.

*class* crispy\_forms.bootstrap.TabHolder(*\*fields*, *css\_id=None*, *css\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#TabHolder)[¶](#crispy_forms.bootstrap.TabHolder "Permalink to this definition")

TabHolder object. It wraps Tab objects in a container.

Parameters

**\*fields**str, LayoutObjectAny number of fields or layout objects as positional arguments to be

rendered within the `<div>`.

**css\_id**str, optionalA DOM id for the layout object which will be added to the `<div>` if

provided. By default None.

**css\_class**str, optionalAdditional CSS classes to be applied in addition to those declared by

the class itself. By default None.

**template**str, optionalOverrides the default template, if provided. By default None.

**\*\*kwargs**dict, optionalAdditional attributes are passed to `flatatt` and converted into

key=”value”, pairs. These attributes are added to the `<div>`.

Examples

Example:

```

TabHolder(

    Tab('form\_field\_1', 'form\_field\_2'),

    Tab('form\_field\_3')

)

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**css\_class**str, optionalCSS classes to be applied to the `<div>`. By default None.

*class* crispy\_forms.bootstrap.UneditableField(*field*, *css\_class=None*, *wrapper\_class=None*, *template=None*, *\*\*kwargs*)[[source]](_modules/crispy_forms/bootstrap.html#UneditableField)[¶](#crispy_forms.bootstrap.UneditableField "Permalink to this definition")

Layout object for rendering fields as uneditable in bootstrap.

Parameters

**fields**strThe name of the field.

**css\_class**str, optionalCSS classes to be applied to the field. These are added to any classes

included in the `attrs` dict. By default `None`.

**wrapper\_class: str, optional**CSS classes to be used when rendering the Field. This class is usually

applied to the `<div>` which wraps the Field’s `<label>` and

`<input>` tags. By default `None`.

**template**str, optionalOverrides the default template, if provided. By default `None`.

**\*\*kwargs**dict, optionalAdditional attributes are converted into key=”value”, pairs. These

attributes are added to the `<div>`.

Examples

Example:

```

UneditableField('field\_name', css\_class="input-xlarge")

```

Attributes

**template**strThe default template which this Layout Object will be rendered

with.

**attrs**dictAttributes to be applied to the field. These are converted into html

attributes. e.g. `data\_id: 'test'` in the attrs dict will become

`data-id='test'` on the field’s `<input>`.

Developer Guide[¶](#developer-guide "Permalink to this heading")

----------------------------------------------------------------

Think this is awesome and want to make it better? Read our contribution page, make it better, and you will be added to the [contributors](https://github.com/django-crispy-forms/django-crispy-forms/blob/main/CONTRIBUTORS.txt) list!

### Contributing[¶](#contributing "Permalink to this heading")

#### Setup[¶](#setup "Permalink to this heading")

##### Fork on GitHub[¶](#fork-on-github "Permalink to this heading")

Before you do anything else, login/signup on GitHub.com and fork django-crispy-forms from <https://github.com/django-crispy-forms/django-crispy-forms>.

##### Clone your fork locally[¶](#clone-your-fork-locally "Permalink to this heading")

If you have git-scm installed, you now clone your git repository using the following command-line argument where <my-github-name> is your account name on GitHub:

```

git clone git@github.com/<my-github-name>/django-crispy-forms.git

```

##### Install requirements[¶](#install-requirements "Permalink to this heading")

Install dependencies for development by **cd**-ing into the crispy-forms folder and then running:

```

pip install -r requirements.txt

```

In addition to these requirements you will also need to install Django itself. To install the current version of Django:

```

pip install django

```

Django-crispy-forms comes with git hook scripts. These can be installed by running:

```

pre-commit install

```

Pre-commit will now run automatically on git-commit and check adherence to the style guide (black, isort & flake8).

#### Build the documentation locally[¶](#build-the-documentation-locally "Permalink to this heading")

If you make documentation changes they can be seen locally.

In the directory where you cloned `django-crispy-forms`:

```

cd docs

pip install -r requirements.txt

make html

```

You can open the file `\_build/html/index.html` and verify the changes.

#### Setting up topic branches and generating pull requests[¶](#setting-up-topic-branches-and-generating-pull-requests "Permalink to this heading")

While it’s handy to provide useful code snippets in an issue, it is better for

you as a developer to submit pull requests. By submitting pull request your

contribution to django-crispy-forms will be recorded by GitHub.

In git it is best to isolate each topic or feature into a “topic branch”. While

individual commits allow you control over how small individual changes are made

to the code, branches are a great way to group a set of commits all related to

one feature together, or to isolate different efforts when you might be working

on multiple topics at the same time.

While it takes some experience to get the right feel about how to break up

commits, a topic branch **must** be limited in scope to a single `issue` as

submitted to an issue tracker.

Also since GitHub pegs and syncs a pull request to a specific branch, it is the

**ONLY** way that you can submit more than one fix at a time. If you submit

a pull from your main branch, you can’t make any more commits to your main branch

without those getting added to the pull.

To create a topic branch, its easiest to use the convenient `-b` argument to `git

checkout`:

```

git checkout -b fix-broken-thing

Switched to a new branch 'fix-broken-thing'

```

You should use a verbose enough name for your branch so it is clear what it is

about. Now you can commit your changes and regularly merge in the upstream

main branch as described below.

When you are ready to generate a pull request, either for preliminary review,

or for consideration of merging into the project you must first push your local

topic branch back up to GitHub:

```

git push origin fix-broken-thing

```

Now when you go to your fork on GitHub, you will see this branch listed under

the “Source” tab where it says “Switch Branches”. Go ahead and select your

topic branch from this list, and then click the “Pull request” button.

Here you can add a comment about your branch. If this in response to

a submitted issue, it is good to put a link to that issue in this initial

comment. The repo managers will be notified of your pull request and it will

be reviewed (see below for best practices). Note that you can continue to add

commits to your topic branch (and push them up to GitHub) either if you see

something that needs changing, or in response to a reviewer’s comments. If

a reviewer asks for changes, you do not need to close the pull and reissue it

after making changes. Just make the changes locally, push them to GitHub, then

add a comment to the discussion section of the pull request.

#### Pull upstream changes into your fork regularly[¶](#pull-upstream-changes-into-your-fork-regularly "Permalink to this heading")

django-crispy-forms is worked on by a lot of people. It is therefore critical that you pull upstream changes from trunk into your fork on a regular basis. Nothing is worse than putting in days of hard work into a pull request only to have it rejected because it has diverged too far from trunk.

To pull in upstream changes:

```

git remote add trunk git://github.com/django-crispy-forms/django-crispy-forms.git

git fetch trunk

```

Check the log to be sure that you actually want the changes, before merging:

```

git log ..django-crispy-forms/main

```

Then merge the changes that you fetched:

```

git merge django-crispy-forms/main

```

For more info, see <https://help.github.com/fork-a-repo/>

#### How to get your Pull Request accepted[¶](#how-to-get-your-pull-request-accepted "Permalink to this heading")

We want your submission. But we also want to provide a stable experience for our users and the community. Follow these rules and you should succeed without a problem!

##### Run the tests![¶](#run-the-tests "Permalink to this heading")

Before you submit a pull request, please run the entire django-crispy-forms test suite via:

```

make test

```

If you don’t have `make` installed the test suite can also be run via:

```

pytest --ds=tests.test\_settings --cov=crispy\_forms

```

The first thing the core committers will do is run this command. Any pull request that fails this test suite will be **rejected**.

##### It’s always good to add tests![¶](#it-s-always-good-to-add-tests "Permalink to this heading")

We’ve learned the hard way that code without tests is undependable. If your pull request comes with tests, it’s got a greater chance to be included. Otherwise the lead will ask you to code them or will help you doing so.

We use the py.test.

Also, keep your tests as simple as possible. Complex tests end up requiring their own tests. We would rather see duplicated assertions across test methods than cunning utility methods that magically determine which assertions are needed at a particular stage. Remember: Explicit is better than implicit.

##### Don’t mix code changes with whitespace cleanup[¶](#don-t-mix-code-changes-with-whitespace-cleanup "Permalink to this heading")

If you change two lines of code and correct 200 lines of whitespace issues in a file the diff on that pull request is functionally unreadable and will be **rejected**. Whitespace cleanups need to be in their own pull request.

##### Keep your pull requests limited to a single issue[¶](#keep-your-pull-requests-limited-to-a-single-issue "Permalink to this heading")

django-crispy-forms pull requests should be as small/atomic as possible. Large, wide-sweeping changes in a pull request will be **rejected**, with comments to isolate the specific code in your pull request. Some examples:

1. If you are fixing a bug in one helper class don’t ‘*cleanup*’ unrelated helpers. That cleanup belongs in another pull request.

2. Changing permissions on a file should be in its own pull request with explicit reasons why.

##### Keep your code simple![¶](#keep-your-code-simple "Permalink to this heading")

Memorize the Zen of Python:

```

>>> python -c 'import this'

```

Please keep your code as clean and straightforward as possible. When we see more than one or two functions/methods starting with \_my\_special\_function or things like \_\_builtins\_\_.object = str we start to get worried. Rather than try and figure out your brilliant work we’ll just **reject** it and send along a request for simplification.

Furthermore, the pixel shortage is over. We want to see:

* helper instead of hpr

* django-crispy-forms instead of dcf

* my\_function\_that\_does\_things instead of mftdt

