What first comes to your mind when you hear the word “Django?” Some people can't help but think about the movie: Django Unchained, some about weird jingos. Well, it’s neither jingo patriotism nor a movie — it’s something that helps developers bring some style to their HTML forms without much effort or time.


Let’s learn how developers can polish up HTML fields with django-crispy-forms

dedicated development teams


What on Earth Are Django-Crispy-Forms?

Django-crispy-forms is a high-level Python web framework. The primary motivation here is to encourage quick development and make an attractive design.


Moreover, the Django framework was built by professional developers. It tackles the issues of web development hassles so that IT specialists can focus on creating their apps pain-free. There’s no need to reinvent the wheel. Django project is free and open for any aspiring developer.


How Does Django Play?


Django DRY (fun word for crispy) forms can help to build reusable programmatic layouts. Here the developer has full control of the rendered HTML without the necessity to write HTML in templates. All this can happen without breaking the standard way of doing things in Django, so it plays nice with any other crispy form application.


Django-crispy-forms is built to support Python 2.7/Python 3.3+ and Django 1.8/Django 1.10+


The application basically gives such options:

  • A filter called |crispy | that will render neat div based forms. You can imagine it as the built-in methods: as_table, as_ul and as_p. The output cannot be tuned up, but it can be easily launched to life.
  • A tag named {% crispy %} will render a Django form that is tailored to the developer’s configuration and particular layout setup. This gives computer gurus lots of “super-powers” without much hassle, helping them to save loads of time.


The Boons of Django-Crispy-Forms

Django-crispy-forms helps developers bring some style to input forms’ properties (i.e., method, CSS classes or “send button”) on the backend. The good news: these Django forms don’t have to be re-written in the template. In this way, the plain Django forms become more readable. It is also easier to render them. The programmer can even restrict them to one life of code.


More significantly, Django-crispy-forms improves the look of the forms. They add CSS classes to all the buttons, individual fields so that an entire crispy form looks gorgeous. 


Installing Django-Crispy-Forms is a Piece of Cake

Developers need to follow a standard procedure to install django-crispy-forms. They need a pack manager “pip” or “easy_install.” Then, they add the installed App ‘cryspy_forms” to the INSTALLED_APPS list.


If the Bootstrap(or any other CSS framework as Foundations) is used, then it needs to be imported to the project. That’s all to it. For more details and advanced options, check out the official django-crispy-forms documentation.


How Django Crispy Forms Layout Saves the Day

how does django play

Django-crispy-forms can define another strong class: Layout. This class is an excellent help for rendering the fields of a form. It opens access so that fields can be ordered and wrapped in structures. Then HTML is added, and various classes are set, etc. All of this is an excellent asset at hand for a busy programmer. 


Now the developer doesn’t have to write a custom form template — no need for programmatic layouts any longer. The programmer can attach the layout to a helper. Layouts are optionally used, but the bottom line here is that they are the best stuff offered by django-crispy-forms. So they shouldn’t be overlooked.  


Layout objects are the building bricks for Layout. They are the DNA of the form-building process.


Feel free to dig deeper into it by reading about Universal layout objects. It’s important to remember that a different template is generated by various components which have a different purpose.


For instance, let’s imagine a developer wants to have a couple of different layouts for their crispy form. How would this form class look like in real life? NB: Some layout objects are tied to a particular template.


Imagine ButtonHolder is for uni_formtemplate_pack, while FormActions is for bootstrap template pack. Here are some django-crispy-forms layout examples: 


from crispy_forms.helper import FormHelper

from crispy_forms.layout import Layout, Fieldset, ButtonHolder, Submit


class ExampleForm(forms.Form):


   def __init__(self, *args, **kwargs):

       self.helper = FormHelper()

       self.helper.layout = Layout(


               'first arg is the legend of the fieldset',








               Submit('submit', 'Submit', css_class='button white')



       super(ExampleForm, self).__init__(*args, **kwargs)


While rendering the form, the developers use now:

{% load crispy_forms_tags %}

{% crispy example_form %}


What’s next? The fields are included in the fieldset, whose legend will be switched to ‘first arg is the legend of the fieldset.’ The order of the fields’ will be in this fashion: like_platform, favorite_watch, favorite_price, favorite_restaurant, and notes.


Then the submit button can be wrapped in a <div class="buttonHolder"> which Django uni-form turns from ashes to beauty. That button is under the jurisdiction of its own CSS class which is set to button white.


Now, let’s say the developer wants to explain the notes. In such a case HTML layout object can be used:




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






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






The fieldset legend is “context-conscious,” and it can be written as if it were a piece of a template (where the crispy form will be rendered to). The HTML object will tag a message before the notes are provided. It’s also “context-aware.” Layout objects such as Fieldset, Div, MultiField, and ButtonHolder can contain other Layout objects within.


Let’s play a bit further. This time we’ll do a different layout for the same crispy form:



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




           css_id = 'special-fields'








This time a MultiField has been used which is a layout object. As a rule of thumb, it can be utilized in the same places as Fieldset. The difference here is: all fields can be rendered wrapped in a div. If some potential errors happen in the form submission, then they are displayed in a list farther from the field.


Welcome to the World of Universal Layout Objects

The layout objects are found in module crispy_forms.layout, but they are not specific to a template pack. Let’s take them one by one and see their usage examples:


  • Div: It wraps fields in a <div>:

Div('form_field_1', 'form_field_2', 'form_field_3', ...)


DISCLAIMER: There is a possibility to set kwargs in all layout objects that will be utilized as HTML attributes. The developer should use css_class as class is a keyword in Python. For example:

Div('form_field_1', style="background: white;", title="Explication title", css_class="bigdivs")


  • HTML: It’s quite a powerful layout object. It should be used to render pure HTML code. In essence, it acts as a Django template. HTML has access to the overall context of the page where the form is being rendered.


  • Field: A principle layout object. It can be used for setting attributes in a field or rendering a particular field with a custom template. That is how the necessity to override the field’s widget can be avoided. That is the way to pass over a weird attrs dictionary:

Field('password', id="password-field", css_class="passwordfields", title="Explanation")

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


This layout object can be used for an easy Django’s widgets extension.


  • Submit: Used to help to create submit button. There are two parameters. The first one is the name attribute of this very button. The second one is the value attribute:

Submit('search', 'SEARCH')

Submit('search', 'SEARCH')

is rendering to:

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


  • Hidden: was creating a hidden input:

Hidden('name', 'value')


  • Button: for creating a button:

Button('name', 'value')


  • Reset: was used to create a reset input:

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


  • Fieldset: It wraps fields in a <fieldset>. The first attribute is the command line for the fieldset legend. As indicated earlier, it acts as a Django template:

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





We’ve just scratched the surface of django-crispy-forms capacities. Of course, more things can be done with their help. For example, django views can switch on "helper." It can also be overwritten.


Django is also helpful if you want to submit class for button creation: <button type="submit" class="btn btn-primary">Sign in</button>. Moreover, developers can create their own templates for specific fields within a form.\


Final Thoughts

Making Forms Crispier than Potato Chips with Django-Crispy-Forms

If you’re curious to delve deeper into the complexities of Django crispy, feel free to digest its official documentation. Additionally, you can watch this video for a better grasp of this topic. 


We are here to make sure that Django plays nice for you! Let your HTML forms look extravagantly beautiful.

Written by:
Denis  Sheremetov
Denis Sheremetov

CTO at Onix-Systems

Development of custom solutions for all sizes of businesses. Ensuring efficient and secure technology use.

LinkedIn IconEmail Icon
Anna Umanenko
Anna Umanenko

Chief Marketing Officer