Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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:

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

I'd like to be able to add something like:

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

However, I can't seem to find a way to access the request in the ModelForm.

My View is like so:

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)

I'm not sure if this is even close to what I should do, but I tried:

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

But I got the error: init() got an unexpected keyword argument 'place_user'

Any ideas on this one? Or can anyone think of a way to filter my ModelChoiceField in the view without needing to pass my request to the ModelForm?

like image 409
Brian Avatar asked Apr 27 '11 15:04

Brian


2 Answers

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)
like image 163
Ivan Virabyan Avatar answered Sep 21 '22 18:09

Ivan Virabyan


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!

like image 25
Yuji 'Tomita' Tomita Avatar answered Sep 18 '22 18:09

Yuji 'Tomita' Tomita