9

I wasn't able to find a way to identify the type of a field in a django template. My solution was to create a simple filter to access the field and widget class names. I've included the code below in case it's helpful for someone else.

Is there a better approach?

## agency/tagutils/templatetags/fieldtags.py
###############################################################
from django import template

register = template.Library()

@register.filter(name='field_type')
def field_type(value):
    return value.field.__class__.__name__

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


## client/project/settings.py
###############################################################

INSTALLED_APPS = (
    # ...
    'agency.tagutils',
)


## client/project/templates/project/field_snippet.html
###############################################################

{% load fieldtags %}

<div class="field {{ field|field_type }} {{ field|widget_type }} {{ field.name }}">
     {{ field.errors }}
    <div class="form_label">
        {{ field.label_tag }}
    </div>
    <div class="form_field">
    {{ field }}
    </div>
</div>


## sample output html
###############################################################
<div class="field CharField TextInput family_name">    
    <div class="form_label">
        <label for="id_family_name">Family name</label>
    </div>
    <div class="form_field">
    <input id="id_family_name" type="text" name="family_name" maxlength="64" />
    </div>
</div>
Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
olivergeorge
  • 355
  • 2
  • 4
  • 8
  • 1
    That's pretty cool, but seems a bit of overengineering? input tags are always character text, and textareas always textareas, etc. and you have id tags to boot. Surely you can get the desired look by putting the same amount of effort into the CSS? – John Mee Sep 21 '09 at 09:13
  • yea, i wonder what's the point of that and what cannot be easily solved with css and/or js? – zalew Sep 21 '09 at 12:28
  • It seems like setting the Widget.attrs value to include a meaningful class / name would be less complex and considerably clearer when looking at the style sheet. – Billy Herren Sep 22 '09 at 16:11
  • 1
    Yeah sure you can style the field itself, but sometimes you need to style it's wrapper according to what it contains, and since there is no parent selector in CSS you're out of luck. Of course, it can be solved with JS, but i'd rather do it in Django. – Daniel Jul 26 '10 at 14:40

1 Answers1

31
class MyForm(forms.Form):
    myfield = forms.CharField(widget=forms.TextInput(attrs={'class' : 'myfieldclass'}))

or, with a ModelForm

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel
        widgets = {
            'myfield': forms.TextInput(attrs={'class': 'myfieldclass'}),
        }

or, when you don't want to redefine the widget

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['myfield'].widget.attrs.update({'class' : 'myfieldclass'})

render normally with {{ form }}

shadfc
  • 6,104
  • 3
  • 25
  • 19
  • 7
    While this seems to be the django way of doing it, I think there should be something in the template system to add a class to a form field. This would be more helpful for front-end only developers so the back-end guys don't have to add classes for them. – Dustin Feb 17 '11 at 22:31
  • 1
    Why not use https://pypi.python.org/pypi/django-widget-tweaks? Example code: {% load widget_tweaks %} {{ form.title|append_attr:"class:css_class_1 css_class_2" }} – Daviddd May 23 '13 at 12:16