下面是从forms.Select类我做了继承(感谢Cat Plus Plus你为我开始使用此)。初始化时,请提供option_title_field参数,指示将哪个字段用于<option>
标题属性。
from django import forms
from django.utils.html import escape
class SelectWithTitle(forms.Select):
def __init__(self, attrs=None, choices=(), option_title_field=''):
self.option_title_field = option_title_field
super(SelectWithTitle, self).__init__(attrs, choices)
def render_option(self, selected_choices, option_value, option_label, option_title=''):
print option_title
option_value = forms.util.force_unicode(option_value)
if option_value in selected_choices:
selected_html = u' selected="selected"'
if not self.allow_multiple_selected:
# Only allow for a single selection.
selected_choices.remove(option_value)
else:
selected_html = ''
return u'<option title="%s" value="%s"%s>%s</option>' % (
escape(option_title), escape(option_value), selected_html,
forms.util.conditional_escape(forms.util.force_unicode(option_label)))
def render_options(self, choices, selected_choices):
# Normalize to strings.
selected_choices = set(forms.util.force_unicode(v) for v in selected_choices)
choices = [(c[0], c[1], '') for c in choices]
more_choices = [(c[0], c[1]) for c in self.choices]
try:
option_title_list = [val_list[0] for val_list in self.choices.queryset.values_list(self.option_title_field)]
if len(more_choices) > len(option_title_list):
option_title_list = [''] + option_title_list # pad for empty label field
more_choices = [(c[0], c[1], option_title_list[more_choices.index(c)]) for c in more_choices]
except:
more_choices = [(c[0], c[1], '') for c in more_choices] # couldn't get title values
output = []
for option_value, option_label, option_title in chain(more_choices, choices):
if isinstance(option_label, (list, tuple)):
output.append(u'<optgroup label="%s">' % escape(forms.util.force_unicode(option_value)))
for option in option_label:
output.append(self.render_option(selected_choices, *option, **dict(option_title=option_title)))
output.append(u'</optgroup>')
else: # option_label is just a string
output.append(self.render_option(selected_choices, option_value, option_label, option_title))
return u'\n'.join(output)
class LocModelForm(forms.ModelForm):
icons = forms.ModelChoiceField(
queryset = Photo.objects.filter(galleries__title_slug = "markers"),
widget = SelectWithTitle(option_title_field='FIELD_NAME_HERE')
)
有什么特别的原因,为什么字段应该在'Meta'内部类而不是'__init__'方法中修改?并且同样的推理适用于修改/添加字段的小部件属性? – hellsgate
@hellsgate在大多数情况下,没有理由不重写'__init__'来设置'widget.attrs'。在大多数用例中,例如修改默认小部件上的html属性*而不是通过'__init__'覆盖来覆盖DRY。不幸的是,对于OP的情况,他将不得不定义一个自定义小部件,因为'
这种方法也可以用来扩展'SelectMultiple'小部件。只是子类'SelectMultiple'并将其传递给自定义的'MySelect'小部件。 – NickBraunagel