Sending request.user object to ModelForm from class based generic view in Django

后端 未结 3 1302
旧巷少年郎
旧巷少年郎 2020-12-05 08:06

So, my goal is to be able to filter a ModelChoiceField queryset in my ModelForm to only include Places that request.user has created.

My ModelForm is simply:

相关标签:
3条回答
  • 2020-12-05 08:27

    I'm on an iPhone, but do this:

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

    Wow that was hard! No indention support!

    0 讨论(0)
  • 2020-12-05 08:28

    To update Yuji's answer for Django 1.10+ (including Django 2.0+), see the example below (note the updated method signature). Yuji's suggested approach keeps the queryset in the view along with the other business logic, and helps keep any form class extending models.ModelForm clean and straightforward.

    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
    
    0 讨论(0)
  • 2020-12-05 08:51

    You need to pop key user from kwargs in PlaceEventForm.__init__() method, to prevent it from going to ModelForm.__init__() method:

    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)
    
    0 讨论(0)
提交回复
热议问题