Question

Alors, mon objectif est d'être en mesure de filtrer un dans mon ModelForm pour inclure uniquement les queryset ModelChoiceField lieux qui request.user a créé.

Mon ModelForm est simplement:

class PlaceEventForm(models.ModelForm):
    class Meta:
        model = Event

Je voudrais pouvoir ajouter quelque chose comme:

def __init__(self, *args, **kwargs):
    super(PlaceEventForm, self).__init__(*args, **kwargs)
    self.fields['place'].queryset = Place.objects.filter(created_by=request.user)

Cependant, je ne peux pas sembler trouver un moyen d'accéder à la demande dans le ModelForm.

Selon moi, comme ceci:

class PlaceEventFormView(CreateView):
    form_class = PlaceEventForm
    template_name = 'events/event_create.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(PlaceEventFormView, self).dispatch(*args, **kwargs)

Je ne sais pas si cela est encore à ce que je dois faire, mais j'essayé:

def get_form_kwargs(self):
    kwargs = super(PlaceEventFormView, self).get_form_kwargs()
    kwargs.update({'place_user': self.request.user})
    return kwargs

Mais je suis l'erreur: init () a obtenu un argument inattendu mot-clé 'place_user'

Toutes les idées sur celui-ci? Ou peut-on penser à un moyen de filtrer mon ModelChoiceField dans la vue, sans avoir besoin de passer ma demande à la ModelForm?

Était-ce utile?

La solution

Vous devez pop user clé kwargs dans la méthode de PlaceEventForm.__init__(), pour l'empêcher d'aller à la méthode de ModelForm.__init__():

views.py:

class PlaceEventFormView(CreateView):
    form_class = PlaceEventForm
    template_name = 'events/event_create.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(PlaceEventFormView, self).dispatch(*args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super(PlaceEventFormView, self).get_form_kwargs()
        kwargs.update({'place_user': self.request.user})
        return kwargs

forms.py:

class PlaceEventForm(models.ModelForm):
    class Meta:
        model = Event

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('place_user')
        # now kwargs doesn't contain 'place_user', so we can safely pass it to the base class method
        super(PlaceEventForm, self).__init__(*args, **kwargs)
        self.fields['place'].queryset = Place.objects.filter(created_by=user)

Autres conseils

Je suis sur un iPhone, mais faire ceci:

def get_form(self, form_class):
     form = super(MyView, self).get_form(form_class)
     form.fields['place'].querset = Place....
     return form

Wow qui était dur! Pas de support indention!

Pour mettre à jour la réponse de Yuji pour Django 1.10+ (y compris Django 2.0+), voir l'exemple ci-dessous (notez la signature de la méthode mise à jour). L'approche proposée par Yuji maintient le queryset dans la vue ainsi que l'autre logique métier, et aide à garder une classe de forme models.ModelForm extension propre et simple.

def get_form(self, form_class=None):
    if form_class is None:
        form_class = self.get_form_class()
    form = super(MyView, self).get_form()
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user)
    return form

Shorter:

def get_form(self, form_class=None):
    form = super(MyView, self).get_form(form_class)
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user)
    return form
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top