2

Je veux limiter les choix d'un ManyToManyField à ceux correspondant à un ForeignKey. Le formulaire s'affiche correctement, mais lors de l'enregistrement des résultats dans une erreur "Sélectionner un choix valide n'est pas l'un des choix disponibles"."Sélectionnez un choix valide <choice> n'est pas l'un des choix disponibles" erreur lors de la soumission ManyToMany ModelForm

Avant d'essayer de limiter le jeu de requête en passant un paramètre dans la vue au formulaire, puis en utilisant ce paramètre pour filtrer le jeu de requête.

Modèles:

class VenueEventTimeslot(models.Model): 
    venue = models.ForeignKey(Venue) 
    name = models.CharField(max_length=255) 

class VenueEvent(models.Model): 
    venue = models.ForeignKey(Venue) 
    event_timeslots = models.ManyToManyField(VenueEventTimeslot)  

class VenueEventForm(ModelForm): 
    event_timeslots = ModelMultipleChoiceField(queryset=None, widget=CheckboxSelectMultiple()) 

    def __init__(self, *args, **kwargs): # limit timeslots to those of the venue only 
     venue_obj = kwargs.pop('venue_obj',None) 
     super(VenueEventForm, self).__init__(*args,**kwargs) 
     self.fields['event_timeslots'].queryset=VenueEventTimeslot.objects.filter(venue=venue_obj) 

    class Meta: 
     model = VenueEvent 
     fields = ['event_timeslots'] 

Vues:

@login_required 
def calendar(request, pk): 
    venue = Venue.objects.get(pk = pk) 

    if request.method == "POST": 
     form = VenueEventForm(request.POST) 
     if form.is_valid(): 
      # form stuff 
     else: 
      form = VenueEventForm(venue_obj = venue) 

    context = {'venue':venue, 'form':form} 
    return render(request, ... , context) 

Cependant, si je passais la queryset de la vue, il fonctionne parfaitement.

Modèles:

class VenueEventTimeslot(models.Model): 
    # same as above 

class VenueEvent(models.Model): 
    # same as above 

class VenueEventForm(ModelForm): 
    class Meta: 
    model = VenueEvent 
    fields = ['date','client_name','event_timeslots'] 
    widgets = { 
     'date': SelectDateWidget(), 
     'event_timeslots': CheckboxSelectMultiple(), 
    } 

Vues:

@login_required 
def calendar(request, pk): 
    venue = Venue.objects.get(pk = pk) 

    if request.method == "POST": 
     form = VenueEventForm(request.POST) 
     if form.is_valid(): 
      # form stuff 
     else: 
      form = VenueEventForm() 
    form.fields['event_timeslots'].queryset=VenueEventTimeslot.objects.filter(venue=venue) 

    context = {'venue':venue, 'form':form} 
    return render(request, ..., context) 

Est-ce que quelqu'un en mesure de faire la lumière sur ce sujet?

+0

donc êtes-vous vous dire modèle de formulaire, __init __() ne fonctionne pas correctement? –

+0

Mettez une réponse en place laissez-moi savoir comment cela fonctionne pour vous. –

Répondre

1

Je viens de résoudre un problème similaire à celui d'hier qui est ici, How To Exclude A Value In A ModelMultipleChoiceField?, mais je pense que le problème avec votre fonction init est la façon dont il est formaté. Plutôt que lieu = lieu_objet, vous devez le remplacer par lieu_publier_obj, car il semble que vous obtenez le point de rendez-vous dans la vue au lieu de VenueEvent, et j'ai reformaté votre formulaire pour le rendre plus net.

forms.py

class VenueEventForm(ModelForm): 

    def __init__(self, *args, **kwargs): # limit timeslots to those of the venue only 
     venue_obj = kwargs.pop('venue_obj') 
     super(VenueEventForm, self).__init__(*args,**kwargs) 
     self.fields['event_timeslots'] = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(), queryset=VenueEventTimeslot.objects.filter(pk=venue_obj)) 

    class Meta: 
     model = VenueEvent 
     fields = ['event_timeslots'] 

views.py

@login_required 
def calendar(request, pk): 
    venue = Venue.objects.get(pk = pk) 
    if request.method == "POST": 
     form = VenueEventForm(request.POST, venue_obj=venue) 
     if form.is_valid(): 
      # form stuff 
     else: 
      print VenueEventForm.errors 

    else: 
     form = VenueEventForm(venue_obj=venue) 
     context = {'venue':venue, 'form':form} 
     return render(request, ... , context) 
+0

Désolé, où voyez-vous lieu = lieu? – wasabigeek

+0

Je vois où vous l'aviez maintenant, j'ai regardé la vue par erreur, laissez-moi voir si je peux éditer ma réponse ici. –

+0

qu'est-ce que vous essayez exactement de faire apparaître dans la fonction __inti__ qu'est-ce que vous essayez de retirer de la liste exactement. –