Skip to content

Instantly share code, notes, and snippets.

@mesuutt
Last active August 23, 2017 13:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mesuutt/94b1a3318e8a1ddbcca78f3eaad2c4d5 to your computer and use it in GitHub Desktop.
Save mesuutt/94b1a3318e8a1ddbcca78f3eaad2c4d5 to your computer and use it in GitHub Desktop.
Custom form widget for add additional attributes to option tags of select on Django forms.
from django import forms
from django.utils.encoding import force_text
from django.utils.html import format_html
from django.utils.safestring import mark_safe
class SelectOptionsWithAttrs(forms.widgets.Select):
def render_options(self, selected_choices):
# Normalize to strings.
selected_choices = set(force_text(v) for v in selected_choices)
output = []
try:
for option_value, option_label, option_attrs in self.choices:
output.append(self.render_option(selected_choices, option_value, option_label, option_attrs))
return '\n'.join(output)
except ValueError:
# Select has optgroups or has not any additional attributes
return super(SelectWithAttrs, self).render_options(selected_choices)
def render_option(self, selected_choices, option_value, option_label, option_attrs=None):
if option_value is None:
option_value = ''
option_value = force_text(option_value)
if not option_attrs:
option_attrs = {}
attrs_html = ''
for attr_key, attr_val in option_attrs.items():
attrs_html += ' {}="{}"'.format(attr_key, attr_val)
attrs_html = mark_safe(attrs_html)
if option_value in selected_choices:
selected_html = mark_safe(' selected="selected"')
if not self.allow_multiple_selected:
# Only allow for a single selection.
selected_choices.remove(option_value)
else:
selected_html = ''
return format_html(
'<option value="{}"{}{}>{}</option>',
option_value,
selected_html,
attrs_html,
force_text(option_label)
)
from django import forms
from form_widgets import SelectOptionsWithAttrs
class ExampleForm(forms.Form):
foo = forms.ChoiceField(label='Foo', widget=SelectOptionsWithAttrs())
def __init__(self, *args, **kwargs):
super(ExampleForm, self).__init__(*args, **kwargs)
choices = (
(1, 'mytext', {'class': 'foo bar', 'data-type': 'my-type', 'data-foo': 'bar'},),
(2, 'mytext2', {'class': 'bar baz', 'data-type': 'my-other-type', 'data-foo': 'bar2'},),
)
self.fields['foo'].choices = choices
# Rendered html of the form field
# <select id="id_foo" name="foo">
# <option value="1" class="foo bar" data-foo="bar" data-type="my-type">mytext</option>
# <option value="2" class="foo baz" data-foo="bar2" data-type="my-other-type">mytext2</option>
# </select>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment