2011-02-23 64 views
13
PLANNING_CHOICES = (
    ('0',u'Every morning'), 
    ('1',u'Every night'), 
    ('2',u'Never'), 
) 

    planning = forms.ChoiceField(
           required=True,  
           choices = PLANNING_CHOICES, 
           ) 

有一个这样的表单字段命名计划,我需要标题属性添加到选择和最终呈现为这样:Django的表单字段选择,添加属性

   <select> 
        <option value="0" title="bla1">Every morning</option> 
        <option value="1" title="bla2">Every night</option> 
        <option value="2" title="bla3">Never</option> 
       </select> 

怎样才可以实现?

回答

19

您必须对该字段进行子类化,才能采取任何方式指定您想要的标题和小部件以显示新属性。

如果你有这样的事情(注:完全未经测试):

from django import forms 
from django.utils.html import escape 
from django.utils.encoding import force_unicode 

class SelectWithTitles(forms.Select): 
    def __init__(self, *args, **kwargs): 
     super(SelectWithTitles, self).__init__(*args, **kwargs) 
     # Ensure the titles dict exists 
     self.titles = {} 

    def render_option(self, selected_choices, option_value, option_label): 
     title_html = (option_label in self.titles) and \ 
      u' title="%s" ' % escape(force_unicode(self.titles[option_label])) or '' 
     option_value = force_unicode(option_value) 
     selected_html = (option_value in selected_choices) and u' selected="selected"' or '' 
     return u'<option value="%s"%s%s>%s</option>' % (
      escape(option_value), title_html, selected_html, 
      conditional_escape(force_unicode(option_label))) 

class ChoiceFieldWithTitles(forms.ChoiceField): 
    widget = SelectWithTitles 

    def __init__(self, choices=(), *args, **kwargs): 
     choice_pairs = [(c[0], c[1]) for c in choices] 
     super(ChoiceFieldWithTitles, self).__init__(choices=choice_pairs, *args, **kwargs) 
     self.widget.titles = dict([(c[1], c[2]) for c in choices]) 

...你应该能够做到这一点:

PLANNING_CHOICES_WITH_TITLES = (
    ('0', 'Every morning', 'bla1'), 
    ('1', 'Every night', 'bla2'), 
    ('2', 'Never',   'bla3'), 
) 

planning = forms.ChoiceFieldWithTitles(
    required=True, choices=PLANNING_CHOICES_WITH_TITLES) 
+0

哇谢谢你,我已经从你的答案中学到了很多! – Hellnar 2011-02-23 12:18:13

+0

不是'render_option'是一个未记录的功能,并且已经从Django 1.11开始删除。 – djbp 2017-11-20 11:23:50

3

你不能。至少不是没有太多的嘲弄。

如果您想要对此生成的标记进行更多的控制,您可能需要使用form_utils.BetterForm,而不是django.forms.Form

5

这是我如何解决这个问题

#models.py 
class Publisher(models.Model): 
    slug = models.Slugfield() 

class Book(forms.ModelForm): 
    publisher = models.ForeignKey(Publisher) 

#forms.py 
from django import forms 
from django.utils.encoding import force_unicode 
from django.utils.html import escape, conditional_escape 

class SelectWithData(forms.Select): 
    def render_option(self, selected_choices, option_value, option_label): 
     obj_data = { 
      obj.id: { 
       data_attr: getattr(obj, data_attr) for data_attr in self.data_attrs 
      } for obj in self.queryset 
     } 

     data_text = u'' 
     for data_attr in self.data_attrs: 
      data_text += u' data-{}="{}" '.format(
       data_attr, 
       escape(force_unicode(obj_data[option_value][data_attr])) 
      ) 

     option_value = force_unicode(option_value) 
     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, **kwargs): 
     data_attrs = kwargs.pop('data_attrs') 
     super(ModelChoiceFieldWithData, self).__init__(queryset, **kwargs) 
     self.widget.queryset = queryset 
     self.widget.data_attrs = data_attrs 


class BookForm(forms.ModelForm): 

    publisher = ModelChoiceFieldWithData(
     queryset=Publisher.objects.all(), 
     data_attrs=('slug',), 
    ) 

#html 

<select id="id_publisher" name="publisher" required="required" title=""> 
    <option value="1" data-slug="first" selected="selected">First Publisher</option> 
    <option value="2" data-slug="second">Second Publisher</option> 
</select> 
相关问题