How to add attributes to form widgets in Django templates

This blog post is about templates in Django, specifically filters or pipes, whatever you call them – in Symfony we used to call them Twig Filters – and how to create them.

Let’s put I have to add a class “form-control” from bootstrap, and another class “select2” from the select2 library into a form widget. Since the form widget is rendered in the backend, it’s not clear how to add attributes before it’s rendered. In this example I had to create a pipe to add attributes to the form widget.

In Symfony’s Twig, it’s pretty simple to add attributes, like so:

{{ form_widget(form.start, {'attr': {'class': 'form-control select2'}} ) }}

In Django’s template we’ll need a bit of a workaround and create the pipe.

Creating the filter file,

from django import template
register = template.Library()

def add_attr(field, css):
    attrs = {}
    definition = css.split(',')

    for d in definition:
        if ':' not in d:
            attrs['class'] = d
            key, val = d.split(':')
            attrs[key] = val

    return field.as_widget(attrs=attrs)

This file should live in a folder called templatetags in your Django app.

Using the pipe in the template

To use it in a Django template, firstly add this widget in the top of the template, similar to the load static widget.

{% load add_attr %}

And now you can use it on any form widget as a function, like so

{{ form.start|add_attr:"class:form-control select2" }}

And that’s it! Your widget will have the classes form-control and select2.

Hope this helps. Alternatively, you can use a django library called django-widget-tweaks that helps you to do this, find the info here.

Happy coding! 🙂