Django Champ À Choix Multiple / Case À Cocher Sélectionner Multiple

J'ai une application Django et je veux afficher des cases à cocher à choix multiples dans le profil d'un utilisateur. Ils pourront ensuite sélectionner plusieurs éléments.

C'est une version simplifiée de mon models.py:

from profiles.choices import SAMPLE_CHOICES

class Profile(models.Model):
    user = models.ForeignKey(User, unique=True, verbose_name_('user'))
    choice_field = models.CharField(_('Some choices...'), choices=SAMPLE_CHOICES, max_length=50)

Et ma classe de la forme:

class ProfileForm(forms.ModelForm):
    choice_field = forms.MultipleChoiceField(choices=SAMPLE_CHOICES, widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = Profile

Et mon views.py:

if request.method == "POST":
    profile_form = form_class(request.POST, instance=profile)
    if profile_form.is_valid():
        ...
        profile.save()
return render_to_response(template_name, {"profile_form": profile_form,}, context_instance=RequestContext(request))

je vois que le POST est uniquement l'envoi d'une valeur:

choice_field u'choice_three' 

Et le local var params est l'envoi d'une liste:

[u'choice_one', u'choice_two', u'choice_three']

Tous les les champs du formulaire d'affichage correct, mais quand je soumettre un article, j'obtiens un message d'erreur

paramètre de liaison D'erreur 7 - probablement un type non supporté.

dois-je traiter le champ de choix multiple plus loin dans la vue? Le type de champ model est-il correct? Toute aide ou référence serait grandement appréciée.

32
demandé sur twampss 2010-04-28 06:30:37

4 réponses

les choix de profil doivent être configurés comme un ManyToManyField pour que cela fonctionne correctement.

... votre modèle doit être comme ceci:

class Choices(models.Model):
  description = models.CharField(max_length=300)

class Profile(models.Model):
  user = models.ForeignKey(User, blank=True, unique=True, verbose_name='user')
  choices = models.ManyToManyField(Choices)

ensuite, synchronisez la base de données et chargez les choix avec les différentes options que vous voulez disponibles.

maintenant, le modèle se construira lui-même...

class ProfileForm(forms.ModelForm):
  Meta:
    model = Profile
    exclude = ['user']

Et enfin, la vue:

if request.method=='POST':
  form = ProfileForm(request.POST)
  if form.is_valid():
    profile = form.save(commit=False)
    profile.user = request.user
    profile.save()
else:
  form = ProfileForm()

return render_to_response(template_name, {"profile_form": form}, context_instance=RequestContext(request))

il faut mentionner que vous pouvez configurer un profil de différentes façons, y compris héritage. Cela dit, cela devrait fonctionner pour vous aussi.

Bonne chance.

32
répondu Brant 2014-07-30 15:45:53

Les modèles.CharField est une représentation de CharField de l'un des choix. Ce que vous voulez est un jeu de choix. Cela ne semble pas être mis en œuvre à django (encore).

Vous utiliser un nombre à beaucoup de domaine, mais qui a l'inconvénient que les choix doivent être mis dans une base de données. Si vous souhaitez utiliser codé en dur choix, ce n'est probablement pas ce que vous voulez.

il y a un morceau de django à http://djangosnippets.org/snippets/1200/ semblent résoudre votre problème, en implémentant un ModelFieldMultipleChoiceField.

13
répondu Webthusiast 2014-06-23 15:55:40

la solution de Brant est absolument correcte, mais j'ai dû la modifier pour qu'elle fonctionne avec plusieurs cases à cocher select et commit=false. Voici ma solution:

models.py

class Choices(models.Model):
    description = models.CharField(max_length=300)

class Profile(models.Model):
   user = models.ForeignKey(User, blank=True, unique=True, verbose_name_('user'))
   the_choices = models.ManyToManyField(Choices)

forms.py

class ProfileForm(forms.ModelForm):
    the_choices = forms.ModelMultipleChoiceField(queryset=Choices.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = Profile
        exclude = ['user']

views.py

if request.method=='POST':
    form = ProfileForm(request.POST)
    if form.is_valid():
        profile = form.save(commit=False)
        profile.user = request.user
        profile.save()
        form.save_m2m() # needed since using commit=False
    else:
        form = ProfileForm()

return render_to_response(template_name, {"profile_form": form}, context_instance=RequestContext(request))
13
répondu twampss 2015-02-05 19:25:19

ManyToManyField n'est pas un bon choix.Vous pouvez utiliser quelques extraits pour implémenter MultipleChoiceField.Vous pouvez être inspiré par Multi-Selectfield with virgule separated values (Field + FormField) Mais il y a un insecte dedans.Et vous pouvez l'installer django-multiselectfield.Ce n'est plus le préfet.

2
répondu wyx 2016-06-10 04:46:36