Django: How can I create a multiple select form? Django: How can I create a multiple select form? django django

Django: How can I create a multiple select form?


I think CheckboxSelectMultiple should work according to your problem.

In your forms.py, write the below code:

from django import formsclass 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>


I did it in this way :

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 CreateViewfrom django.core.urlresolvers import reverseurlpatterns = 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> 

It is works fine in my example, If you need something more, just ask me!!


Regarding to my second question this is the solution. An extending class:

from django import formsfrom django.utils.encoding import force_unicodefrom itertools import chainfrom django.utils.html import escape, conditional_escapeclass 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", {}]    ]