【问题标题】:Django: How can I create a multiple select form?Django:如何创建多选表单?
【发布时间】:2013-03-01 20:23:11
【问题描述】:

我是 Django/Python 的初学者,我需要创建一个多选表单。我知道这很容易,但我找不到任何例子。我知道如何使用小部件创建 CharField,但我对 fields.py 中的所有选项感到困惑。

例如,我不知道以下哪一项最适合多选表单。

'ChoiceField', 'MultipleChoiceField',
'ComboField', 'MultiValueField',
'TypedChoiceField', 'TypedMultipleChoiceField'

这是我需要创建的表单。

        <form action="" method="post" accept-charset="utf-8">
        <select name="countries" id="countries" class="multiselect" multiple="multiple">
            <option value="AUT" selected="selected">Austria</option>
            <option value="DEU" selected="selected">Germany</option>
            <option value="NLD" selected="selected">Netherlands</option>
            <option value="USA">United States</option>
        </select>
        <p><input type="submit" value="Continue &rarr;"></p>
    </form>

编辑:

还有一个小问题。如果我想为每个选项添加一个属性,例如 data:

 <option value="AUT" selected="selected" data-index=1>Austria</option>

我该怎么做?

感谢您的帮助!

【问题讨论】:

    标签: python django forms field multiple-select


    【解决方案1】:

    我认为CheckboxSelectMultiple 应该根据您的问题工作。

    在您的forms.py 中,编写以下代码:

    from django import forms
    
    
    class CountryForm(forms.Form):
        OPTIONS = (
            ("AUT", "Austria"),
            ("DEU", "Germany"),
            ("NLD", "Neitherlands"),
        )
        Countries = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,
                                              choices=OPTIONS)
    

    在您的views.py 中,定义以下函数:

    def countries_view(request):
        if request.method == 'POST':
            form = CountryForm(request.POST)
            if form.is_valid():
                countries = form.cleaned_data.get('countries')
                # do something with your results
        else:
            form = CountryForm
    
        return render_to_response('render_country.html', {'form': form},
                                  context_instance=RequestContext(request))
    

    在你的render_country.html

    <form method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <input type='submit' value='submit'>
    </form>
    

    【讨论】:

    • 是的,这只是一件小事......如果我想为每个选项添加一个像这样的数据属性 我该怎么做?还缺少最后一个未选择的选项。还是谢谢
    • 不确定!!将表格制作为模型表格。我相信至少在后端会关联一个主键。需要检查一下。
    • 如果我的第一个答案满足您的查询,请考虑接受这个答案。 :)
    • 很好的答案@vibhor,但如代码中所述,"AUT" != "Australia" 是奥地利。很抱歉成为一个书呆子,我们澳大利亚人得到了很多,我们对此有点敏感:-)
    【解决方案2】:

    我是这样做的:

    forms.py

    class ChoiceForm(ModelForm):
        class Meta:
            model = YourModel
    
        def __init__(self, *args, **kwargs):
            super(ChoiceForm, self).__init__(*args, **kwargs)
            self.fields['countries'] =  ModelChoiceField(queryset=YourModel.objects.all()),
                                                 empty_label="Choose a countries",)
    

    urls.py

    from django.conf.urls.defaults import * 
    from django.views.generic import CreateView
    from django.core.urlresolvers import reverse
    
    urlpatterns = patterns('',
        url(r'^$',CreateView.as_view(model=YourModel, get_success_url=lambda: reverse('model_countries'),
            template_name='your_countries.html'), form_class=ChoiceForm, name='model_countries'),)
    

    your_countries.html

    <form action="" method="post">
        {% csrf_token %}
        {{ form.as_table }}
        <input type="submit" value="Submit" />
    </form> 
    

    在我的例子中效果很好,如果你需要更多的东西,尽管问我!!

    【讨论】:

      【解决方案3】:

      关于我的第二个问题,这是解决方案。扩展类:

      from django import forms
      from django.utils.encoding import force_unicode
      from itertools import chain
      from django.utils.html import escape, conditional_escape
      
      class Select(forms.Select):
          """
          A subclass of Select that adds the possibility to define additional 
          properties on options.
      
          It works as Select, except that the ``choices`` parameter takes a list of
          3 elements tuples containing ``(value, label, attrs)``, where ``attrs``
          is a dict containing the additional attributes of the option.
          """
          def render_options(self, choices, selected_choices):
              def render_option(option_value, option_label, attrs):
                  option_value = force_unicode(option_value)
                  selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
                  attrs_html = []
                  for k, v in attrs.items():
                      attrs_html.append('%s="%s"' % (k, escape(v)))
                  if attrs_html:
                      attrs_html = " " + " ".join(attrs_html)
                  else:
                      attrs_html = ""
                  return u'<option value="{0}"{1}{2}>{3}</option>'.format(
                      escape(option_value), selected_html, attrs_html, 
                      conditional_escape(force_unicode(option_label))
                      )
                  '''
                  return u'<option value="%s"%s%s>%s</option>' % (
                      escape(option_value), selected_html, attrs_html,
                      conditional_escape(force_unicode(option_label)))
                  '''
              # Normalize to strings.
              selected_choices = set([force_unicode(v) for v in selected_choices])
              output = []
              for option_value, option_label, option_attrs in chain(self.choices, choices):
                  if isinstance(option_label, (list, tuple)):
                      output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
                      for option in option_label:
                          output.append(render_option(*option))
                      output.append(u'</optgroup>')
                  else:
                      output.append(render_option(option_value, option_label,
                          option_attrs))
              return u'\n'.join(output)
      
      class SelectMultiple(forms.SelectMultiple, Select):
          pass
      

      例子:

      OPTIONS = [
              ["AUT", "Australia", {'selected':'selected', 'data-index':'1'}],
              ["DEU", "Germany", {'selected':'selected'}],
              ["NLD", "Neitherlands", {'selected':'selected'}],
              ["USA", "United States", {}]
          ]
      

      【讨论】:

        【解决方案4】:

        ModelMultipleChoiceField 是你的朋友。 CharField 能够存储一个选择,但不能存储多个,无需额外的工作,我建议不要这样做。

        API doc for ModelMultipleChoiceField

        【讨论】:

          【解决方案5】:

          您还可以在表单类中将国家字段定义为

          Countries = forms.MultipleChoiceField(widget=forms.SelectMultiple,
                                                       choices=OPTIONS_TUPPLE)
          

          我不知道 SelectMultiple 和 CheckboxSelectMultiple 哪个更好,但也可以。

          有关更多详细信息,您可以使用有关 widgets 的 django 文档。

          【讨论】:

            【解决方案6】:

            当您想要选择多个值时,使用 widget=forms CheckboxSelectMultiple 非常困难。 (记住多选是针对多对多键字段)

            在这种情况下 SelectMultiple 更好,因为您可以使用 ctrl 选择多个项目或使用 ctrl+a 选择所有项目。

            class MyModalForm(forms.ModelForm):
                class Meta:
                model = MyModel
                    widgets = {            
                        'products': forms.SelectMultiple(attrs={'required': True})
                    }
            

            如果你想要多选的动态值,你可以使用 init

            class MyModalForm(forms.ModelForm):
                class Meta:
                model = MyModel
                    widgets = {            
                        'products': forms.SelectMultiple(attrs={'required': True})
                    }
                def __init__(self, *args, **kwargs):
                    selected_products = kwargs.pop('selected_products', None)   ##queryset returned from function
                    self.fields['products'].queryset = selected_products
                    self.fields['orders'].queryset = OrderModal.objects.filter(pk=2)
            

            【讨论】:

              猜你喜欢
              • 2012-08-15
              • 2017-10-10
              • 2011-08-24
              • 2012-11-12
              • 2012-08-09
              • 2018-10-07
              • 1970-01-01
              • 2021-09-02
              相关资源
              最近更新 更多