17

我是 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>

我该怎么做?

谢谢你的帮助!

4

6 回答 6

40

我认为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>
于 2013-03-13T18:41:55.567 回答
6

我是这样做的:

表格.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",)

网址.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> 

在我的示例中效果很好,如果您需要更多内容,请问我!

于 2013-03-13T18:49:15.197 回答
2

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

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", {}]
    ]
于 2013-03-18T13:04:55.777 回答
1

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

ModelMultipleChoiceField 的 API 文档

于 2013-03-13T18:14:39.017 回答
1

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

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

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

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

于 2016-04-06T10:39:14.313 回答
1

当您想要选择多个值时,使用 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)
于 2021-02-24T11:32:06.763 回答