Django: How to create a multiple choice form?

I am starting to work in Django / Python and I need to create a multiple selection form. I know this easily, but I cannot find any example. I know how to create a CharField with widgets, but I got confused in all the parameters inside fields.py .

For example, I do not know which of the following options is best for multiple forms of selection.

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

And here is the form I need to create.

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

EDIT:

Another little question. If I want to add another attribute to each option, for example:

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

How can i do this?

Thanks for any help!

+11
python django forms field multiple-select
source share
5 answers

I think CheckboxSelectMultiple should work according to your problem.

In your forms.py write the following code:

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

In your views.py define the following function:

 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)) 

In your render_country.html :

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

I did it as follows:

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> 

This works well in my example. If you need anything else, just ask me !!

+4
source share

As for my second question, this is the solution. Expanding Class:

 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 

Example:

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

ModelMultipleChoiceField is your friend. CharField is capable of storing one choice, but not several, without any additional work that I would recommend against.

API Document for ModelMultipleChoiceField

+1
source share

You can also define the country field in your form class as

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

I don't know which one is better in SelectMultiple and CheckboxSelectMultiple, but it also works.

For more information, you can use the django documentation on widgets .

+1
source share

All Articles