drec4s
drec4s

Reputation: 8077

Django Forms - Change widget attributes

I want to define a class attribute for the <option/> tags within a django ChoiceField, how can I do that?

I tried to set the widget class, and specifying an attribute like so, in forms.py:

field = forms.ChoiceField(choices=[(1, 'foo'), (2, 'bar')], widget=forms.Select(attrs={'class': 'form-control'}))

And rendering inside my template.html like this:

{{ form.field }}

The output is:

<select name="field" class="form-control" id="id_field">
   <option value="1">foo</option>
   <option value="2">bar</option>
</select>

And what I want to have is this:

<select name="field" class="form-control" id="id_fields">
   <option class="form-control" value="1">foo</option>
   <option class="form-control" value="2">bar</option>
</select>

What is the easiest way to do this?

Upvotes: 1

Views: 4177

Answers (2)

MattRowbum
MattRowbum

Reputation: 2192

The easiest way to achieve this is to subclass the Select widget and set option_inherits_attrs to True:

class CustomSelect(forms.Select):
    option_inherits_attrs = True

Then use your custom widget when creating the form:

class TestForm(forms.Form):
    items = forms.ChoiceField(
        choices=[(1, 'foo'), (2, 'bar')],
        widget=CustomSelect(
            attrs={'class': 'form-control'}
        )

Upvotes: 2

Jorge Mauro
Jorge Mauro

Reputation: 383

You may create a Template Tag and write a custom template field. It's the best option if you want to reuse attributes.

The app should contain a templatetags directory, at the same level as models.py, views.py, etc. If this doesn’t already exist, create it - don’t forget the __init__.py file to ensure the directory is treated as a Python package.


Create this structure inside your app's folder


Inside filters.py

from django import template
register = template.Library()

@register.filter(name='addclass')
def addclass(value, arg):
    return value.as_widget(attrs={'class': arg})


Add {% load filters %} to your template.html, before {% block content %}


That's how you apply your filter:

{{form.field|addclass:'form-control'}}


Now you should forget about adding classes to your HTML elements inside forms.py


If you disliked the Template Tag way or maybe are just looking for a low-cost temporary solution, you should take a look at this link.

Another way of solving the same problem

Upvotes: 0

Related Questions