<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=338168267432629&amp;ev=PageView&amp;noscript=1">
Programming

Awesome forms with django-crispy-forms

Django-crispy-forms is a third-party Django application which lets you create beautiful forms in “a very elegant and DRY way”. Best of all—you don’t need to code form templates unless you really want to. The resulting form markup, by default, is compatible with Twitter Bootstrap 2. If you want to use Bootstrap …


Django-crispy-forms is a third-party Django application which lets you create beautiful forms in “a very elegant and DRY way”. Best of all—you don’t need to code form templates unless you really want to.

The resulting form markup, by default, is compatible with Twitter Bootstrap 2. If you want to use Bootstrap 3 to render your forms, add the following setting to your settings.py:

CRISPY_TEMPLATE_PACK = 'bootstrap3'

To give a brief demonstration of what `django-crispy-forms` can do, let us try creating a user profile form in Django.

We begin with a simple user model:

class User(AbstractUser):
    COUNTRIES = ()   # Contents are left as an exercise to the reader

    # Address
    address1 = models.CharField(max_length=50)
    address2 = models.CharField(max_length=50)
    city = models.CharField(max_length=50)
    state = models.CharField(max_length=50)
    country = models.CharField(max_length=50, choices=COUNTRIES)

    # Contact
    mobile = models.CharField(max_length=32)
    home = models.CharField(max_length=32)
    office = models.CharField(max_lenghth=32)
    twitter = models.CharField(max_length=100)

    def __unicode__(self):
        return self.username

This example works with custom user models available since Django 1.5.

At this point, we will create a form that will correspond with this model. Something like this perhaps?

from django import forms

class UserForm(forms.ModelForm):
    class Meta:
        model = User # Your User model

This cannot be written more concisely, don’t you think?

Now we’ll see what happens when you try to render this form in a template.

<form action="" method="POST">
    
    
    <input type="submit" value="Submit">
</form>
cripsy_form_profile

Looks simple enough, until you need to skin the form, adjust the layout for each field, group the fields into categories, and so on. The form template will get complicated very quickly. I am sure you get what I mean.

Adding crispy-forms to the mix

To use `django-crispy-forms`, you will need to install the app via `pip`, and then add `crispy_forms` in your `INSTALLED_APPS` setting.

The simplest crispy-forms form will not require you to make any changes to the model form class. The template will need to change, however:

 

Running your project and viewing the rendered template, what you will see is a beautifully rendered form (especially if you are using Twitter Bootstrap), without using any tables or lists. The form tags and the CSRF token are already added for your benefit.

cripsy_form_profile2

Helpers

The best thing about `crispy-forms` is the form helper, defined under your form as the `helper` attribute. Anything you need to define in the form, like the form’s action, method and even layout are set in the helper. No need to go back and forth between your form class and any template that use the form!

Say we don’t want crispy-forms automatically adding the form tag. This scenario happens when your template is composed of several forms under a single form tag. You will need to set form_tag to False in the helper.

from django import forms
from crispy_forms.helper import FormHelper

class UserForm(forms.ModelForm):
    helper = FormHelper()
    helper.form_tag = False

    class Meta:
        model = User # Your user model

You will also need to change the template to define the form tag yourself:

<form action="" method="POST">

</form>

This scenario may be more common on your project; if so, go ahead and use this mixin:

from django import forms
from crispy_forms.helper import FormHelper

class NoFormTagCrispyFormMixin(object):
    @property
    def helper(self):
        if not hasattr(self, '_helper'):
            self._helper = FormHelper()
            self._helper.form_tag = False
        return self._helper

Customizing your form’s layout

Let’s say you need to need to have address and contact information in their own tabs in the template. Even using Twitter Bootstrap, you will find that you will need to do a lot of HTML coding in order to accomplish this task.

Using crispy-forms will simplify this task for you. What you do is define the form’s `layout` in the helper. Like so:

from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout
from crispy_forms.bootstrap import TabHolder, Tab

class UserForm(forms.ModelForm):
    helper = FormHelper()
    helper.form_tag = False
    helper.layout = Layout(
        TabHolder(
            Tab(
                'Basic Information',
                'first_name',
                'last_name'
            ),
            Tab(
                'Address',
                'address1',
                'address2',
                'city',
                'state',
                'country'
            ),
            Tab(
                'Contact',
                'email',
                'mobile',
                'home',
                'office',
                'twitter'
            )
        )
    )

    class Meta:
        model = User # Your User model

You do not need to make any additional changes to the template. Note, however, that the fields you include in the layout must match the fields that your form will be expecting.

Run your project and behold, your user profile form, all set, looking pretty.

cripsy_form_finished

Conclusion

There are a lot more customization options available in django-crispy-forms. Head over to the documentation and read all about it.

Similar posts

Get notified about the latest in Tech

Be the first to know about new tech from the experts at Bixly!