Je suis débutant dans Django/Python et je dois créer un formulaire de sélection multiple. Je sais que c'est facile mais je ne trouve aucun exemple. Je sais comment créer un CharField avec un widget mais je me perds dans toutes les options de fields.py .
Par exemple, je ne sais pas lequel des éléments suivants convient le mieux à un formulaire à sélection multiple.
'ChoiceField', 'MultipleChoiceField',
'ComboField', 'MultiValueField',
'TypedChoiceField', 'TypedMultipleChoiceField'
Et voici la forme que je dois créer.
<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 →"></p>
</form>
MODIFIER:
Encore une petite question. Si je veux ajouter à chaque option un attribut supplémentaire comme data:
<option value="AUT" selected="selected" data-index=1>Austria</option>
Comment puis-je le faire?
Merci pour toute aide!
Je pense que CheckboxSelectMultiple devrait fonctionner. Selon votre problème, dans votre formulaire, votre code ci-dessous
from Django import forms
class CountryForm(forms.Form):
OPTIONS = (
("AUT", "Austria"),
("DEU", "Germany"),
("NLD", "Neitherlands"),
)
Countries = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,
choices=OPTIONS)
EDIT: J'ai pensé écrire un flux de code complet pour que vous puissiez mieux le comprendre. Parce que vous pourriez vous embrouiller
Dans votre Views.py, définissez la fonction suivante
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))
Dans votre render_country.html
<form method='post'>
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='submit'>
</form>
J'espère que cela vous aidera. Faites-moi savoir si c'est ce à quoi vous vous attendiez.
Je l'ai fait de cette façon:
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>
Cela fonctionne bien dans mon exemple. Si vous avez besoin de quelque chose de plus, demandez-le moi !!
En ce qui concerne ma deuxième question, c'est la solution. Une classe en extension:
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
Exemple:
OPTIONS = [
["AUT", "Australia", {'selected':'selected', 'data-index':'1'}],
["DEU", "Germany", {'selected':'selected'}],
["NLD", "Neitherlands", {'selected':'selected'}],
["USA", "United States", {}]
]
ModelMultipleChoiceField est votre ami. Un CharField est capable de stocker une sélection, mais pas plusieurs, sans un travail supplémentaire, ce que je déconseillerais.
Vous pouvez également définir le champ pays dans votre classe de formulaire en tant que
Countries = forms.MultipleChoiceField(widget=forms.SelectMultiple,
choices=OPTIONS_TUPPLE)
Je ne sais pas lequel est le meilleur dans SelectMultiple et CheckboxSelectMultiple mais cela fonctionne aussi.
Pour plus de détails, vous pouvez utiliser la documentation de Django sur widgets .