9e_scq
Last Updated: September 12, 2017
·
2.959K
· dorfire

Style Django form widgets individually

In a recent project I came across the need to give specific form widgets (e.g. PasswordInput) different CSS classes.

My solution is a class decorator that changes those widgets' attr properties:

def _widget_add_classes(widget, classes):
    initial_classes = widget.attrs.get('class', '')
    widget.attrs['class'] = '%s %s' % (initial_classes, classes) if initial_classes else classes

def style_widgets(widget_classes):
    def wrapper(form_cls):
        for field in form_cls.base_fields.itervalues():
            widget_cls = field.widget.__class__.__name__
            if widget_cls in widget_classes:
                _widget_add_classes(field.widget, widget_classes[widget_cls])
        return form_cls
    return wrapper

Example usage:

@style_widgets({'PasswordInput': 'smallinput'})
class EmailRegistrationForm(forms.Form):
    email = forms.EmailField(label=_('Email address'))
    password1 = forms.CharField(
                    label=_('Password'),
                    widget=forms.PasswordInput)
    password2 = forms.CharField(
                    label=_('Password confirmation'),
                    widget=forms.PasswordInput)

I used the same technique to style individual fields by their name. Of course, any other identifier can be used: label / max_length / whatever.