10

I've created a custom template for rendering form fields:

<tr class="{{field.field.widget.attrs.class}}">
    <th class="label">
        <label for="{{field.auto_id}}">
            {{field.label}}
            {% if not field.field.required %}<span class="optional">(optional)</span>{% endif %}
        </label>
    </th>
    <td class="field">
        {{field}}
        {% if field.errors %}<label class="error" for="{{field.auto_id}}">{{field.errors.0}}</label>{% endif %}
        {% if field.help_text %}<small class="help-text">{{field.help_text}}</small>{% endif %}
    </td>
</tr>

But I want to check if the widget is a checkbox, and if so, render it differently. How can I do that in the template?

maciejwww
  • 1,067
  • 1
  • 13
  • 26
mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • Hi - is there a particular reason why you need to do it in the template, rather than setting a custom widget in the form class? – Steve Jalim Oct 13 '10 at 19:03
  • 1
    @stevejalim: I can create a custom widget, but it doesn't solve the issue. I want to set colspan=2 and have the label on the right side. This is an issue with how the table row is laid out, not with how the widget is rendered. – mpen Oct 13 '10 at 19:05
  • gotcha. One (hacky) way to do it is to pass in a list of fields known to be checkboxes and each time you render the field, check if it's name is in that list, and if so, set your colspan there. Icky, though ;o) – Steve Jalim Oct 13 '10 at 20:00
  • Very icky. I'm trying to clean up all that ick right now, not add more to it :) – mpen Oct 13 '10 at 20:10
  • Similar question: http://stackoverflow.com/questions/1809874/get-type-of-django-form-widget-from-within-template – Flimm Aug 12 '16 at 13:42

3 Answers3

20

Use a custom template filter!

In yourapp/templatetags/my_custom_tags.py:

from django import template
from django.forms import CheckboxInput

register = template.Library()

@register.filter(name='is_checkbox')
def is_checkbox(field):
  return field.field.widget.__class__.__name__ == CheckboxInput().__class__.__name__

In your template:

{% load my_custom_tags %}
 
{% if field|is_checkbox %}
  do something
{% endif %}

Side note on implementation: when I don't instantiate a CheckboxInput, the class name is MediaDefiningClass.

>>> form django.forms import CheckboxInput
KeyboardInterrupt
>>> CheckboxInput.__class__.__name__
'MediaDefiningClass'
aj3sh
  • 366
  • 3
  • 10
davidtingsu
  • 1,090
  • 1
  • 10
  • 17
  • 4
    And today there's a special Django utility application which has similar checker and other stuff: https://pypi.python.org/pypi/django-form-utils#is-checkbox – rudyryk May 04 '15 at 09:58
  • 2
    I'd say that it's cleaner to use something like this: `return isinstance(field.field.widget, CheckboxInput)`. – Thibault J Sep 26 '16 at 14:10
11

{{ field.field.widget.input_type }} will get you this info for a lot of widgets, but not all. I'm not sure if it'll work for the default checkbox widget or not. Worth a shot.

mpen
  • 272,448
  • 266
  • 850
  • 1,236
Jeff Croft
  • 361
  • 3
  • 6
  • 1
    Don't think CheckboxInput has this attribute... it does however appear to have a `check_test` attribute... I don't know if it's unique to the checkbox input...but it's working for now... bit of a hack though. – mpen Oct 14 '10 at 03:47
7

It is kind of late to answer, but I implemented something similar to what is done in Django's admin.

First, I added a new attribute is_checkbox to the Field class:

# forms.py
from django import forms
from django.forms.fields import Field
setattr(Field, 'is_checkbox', lambda self: isinstance(self.widget, forms.CheckboxInput ))

Then, I can easily detect a CheckboxInput widget in the template. Here is an example to render checkboxes to the left and other widgets to the right:

{% if field.field.is_checkbox %}
    {{ field }} {{ field.label_tag }}
{% else %}
    {{ field.label }} {{ field }}
{% endif %}
Alexandre
  • 1,245
  • 1
  • 13
  • 22