Skip to content

Instantly share code, notes, and snippets.

@paveltyavin
Last active August 29, 2015 14:09
Show Gist options
  • Save paveltyavin/8b201798189fb57d50a2 to your computer and use it in GitHub Desktop.
Save paveltyavin/8b201798189fb57d50a2 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from django import forms
from django.utils.html import escape, conditional_escape
from django.utils.encoding import force_unicode
def get_attr(obj, attr):
if hasattr(obj, attr):
res = getattr(obj, attr)
if hasattr(res, '__call__'):
return res()
else:
return res
return ''
class SelectWithData(forms.Select):
def render_option(self, selected_choices, option_value, option_label):
data_text = u''
option_value = force_unicode(option_value)
if self.queryset is None:
self.queryset = self.get_queryset()
if option_value:
obj = next(x for x in self.queryset if unicode(x.pk) == option_value)
obj_data = {
data_attr: get_attr(obj, data_attr) for data_attr in self.data_attrs
}
for data_attr in self.data_attrs:
data_text += u' data-{}="{}" '.format(
data_attr,
escape(force_unicode(obj_data[data_attr]))
)
selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
return u'<option value="{}"{}{}>{}</option>'.format(
escape(option_value),
data_text,
selected_html,
conditional_escape(force_unicode(option_label))
)
class ModelChoiceFieldWithData(forms.ModelChoiceField):
widget = SelectWithData
def __init__(self, queryset, get_queryset=None, **kwargs):
data_attrs = kwargs.pop('data_attrs')
super(ModelChoiceFieldWithData, self).__init__(queryset, **kwargs)
if get_queryset is None:
self.widget.queryset = queryset
self.widget.get_queryset = None
else:
self.widget.queryset = None
self.widget.get_queryset = get_queryset
self.widget.data_attrs = data_attrs
class OrderForm(forms.ModelForm):
city = ModelChoiceFieldWithData(
required=False,
data_attrs=('id','slug',),
queryset=City.objects.all(),
get_queryset=lambda: City.objects.all().prefetch_related('cityshipping_set'),
)
shipping = ModelChoiceFieldWithData(
required=False,
data_attrs=('price',),
queryset=Shipping.objects.all(),
)
<select id="id_city" name="city" title="">
<option value="1" data-id="1" data-slug="moskva" selected="selected">Moscow</option>
<option value="2" data-id="2" data-slug="piter" selected="selected">Saint-Petersburg</option>
</select>
<select id="id_shipping" name="shipping" title="">
<option value="1" data-price="100">Fast Delivery</option>
<option value="2" data-price="200">Slow Shipping</option>
</select>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment