How do I create a Django form that displays a checkbox label to the right of the checkbox? How do I create a Django form that displays a checkbox label to the right of the checkbox? python python

How do I create a Django form that displays a checkbox label to the right of the checkbox?


Here's a solution I've come up with (Django v1.1):

{% load myfilters %}[...]{% for field in form %}    [...]    {% if field.field.widget|is_checkbox %}      {{ field }}{{ field.label_tag }}    {% else %}      {{ field.label_tag }}{{ field }}    {% endif %}    [...]{% endfor %}

You'll need to create a custom template tag (in this example in a "myfilters.py" file) containing something like this:

from django import templatefrom django.forms.fields import CheckboxInputregister = template.Library()@register.filter(name='is_checkbox')def is_checkbox(value):    return isinstance(value, CheckboxInput)

More info on custom template tags available here.

Edit: in the spirit of asker's own answer:

Advantages:

  1. No futzing with CSS.
  2. The markup ends up looking the way it's supposed to.
  3. I didn't hack Django internals. (but had to look at quite a bunch)
  4. The template is nice, compact and idiomatic.
  5. The filter code plays nice regardless of the exact values of the labels and input field names.

Disadvantages:

  1. There's probably something somewhere out there that does it better and faster.
  2. Unlikely that the client will be willing to pay for all the time spent on this just to move the label to the right...


I took the answer from romkyns and made it a little more general

def field_type(field, ftype):    try:        t = field.field.widget.__class__.__name__        return t.lower() == ftype    except:        pass    return False

This way you can check the widget type directly with a string

{% if field|field_type:'checkboxinput' %}    <label>{{ field }} {{ field.label }}</label>{% else %}    <label> {{ field.label }} </label> {{ field }}{% endif %}


All presented solutions involve template modifications, which are in general rather inefficient concerning performance. Here's a custom widget that does the job:

from django import formsfrom django.forms.fields import BooleanFieldfrom django.forms.util import flatattfrom django.utils.encoding import force_textfrom django.utils.html import format_htmlfrom django.utils.translation import ugettext as _class PrettyCheckboxWidget(forms.widgets.CheckboxInput):    def render(self, name, value, attrs=None):        final_attrs = self.build_attrs(attrs, type='checkbox', name=name)        if self.check_test(value):            final_attrs['checked'] = 'checked'        if not (value is True or value is False or value is None or value == ''):            final_attrs['value'] = force_text(value)        if 'prettycheckbox-label' in final_attrs:            label = _(final_attrs.pop('prettycheckbox-label'))        else:            label = ''        return format_html('<label for="{0}"><input{1} /> {2}</label>', attrs['id'], flatatt(final_attrs), label)class PrettyCheckboxField(BooleanField):    widget = PrettyCheckboxWidget    def __init__(self, *args, **kwargs):        if kwargs['label']:            kwargs['widget'].attrs['prettycheckbox-label'] = kwargs['label']            kwargs['label'] = ''        super(PrettyCheckboxField, self).__init__(*args, **kwargs)# usage in formclass MyForm(forms.Form):    my_boolean = PrettyCheckboxField(label=_('Some label'), widget=PrettyCheckboxWidget())

I have PrettyCheckboxWidget and PrettyCheckboxField in an extra file, so they may be imported where needed. If you don't need translations, you can remove the ugettext parts. This code works on Django 1.5 and is untested for lower versions.

Advantages:

  • Highly performant, needs no template modifications
  • Easy to use as a custom widget

Disadvantages:

  • "as_table" renders the checkbox + label inside the second column
  • {{ field.label }} inside the template is empty. The label is instead bound to {{ field }}
  • More work than I planned on doing on a Saturday ;-)