How to Integrate Semantic UI with Django and Crispy Forms

This post explains how to integrate Semantic UI with Django’s Crispy Forms. After a lot of troubleshooting, it started working. It should be possible to improve parts of this process in the future, but it works for now.

Step 1

Install Crispy Forms. See the docs for instructions.

Step 2

I downloaded this code from Github. Save it in templates/semantic-ui/.

Step 3

Put this code in settings.py:

CRISPY_TEMPLATE_PACK = 'semantic-ui'
CRISPY_ALLOWED_TEMPLATE_PACKS = ('semantic-ui')

Step 4

Create a form in one of your Django apps. The example below is modified from the Crispy Forms docs.

from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit


class ExampleForm(forms.Form):

    def __init__(self, *args, **kwargs):
        super(ExampleForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_id = 'someId'
        self.helper.form_class = 'some-class'
        self.helper.form_method = 'post'
        self.helper.form_action = 'sample_form_name'

        # Note that the submit button is added separately, with a Semantic UI class.
        self.helper.add_input(Submit('submit', 'Submit',
                              css_class='ui button'))

    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,
    )

Step 5

Update your view:

def sample_form(request):
    context = {'form': ExampleForm}

    return render(request, 'someform/someform_create.html', context)

Step 6

Put the form in a template:

{% extends 'coreapp/layouts/main.html' %}
{% load crispy_forms_tags %}

{% block content %}
<div class="ui form">
    {% crispy form %}
</div>
{% endblock %}

All Done

If it doesn’t work, or if you have suggestions for improvement, please comment below!

Update: a commenter in the old blog mentioned this tip on 2017-11-07:

This can now be done even more easily with Django Semantic UI Forms. It even includes layout capability.