2011-04-27 67 views
12

因此,我的目標是能夠過濾ModelForm中的ModelChoiceField查詢集,以僅包含request.user創建的地方。將request.user對象從Django中基於類的通用視圖發送到ModelForm

我的ModelForm很簡單:

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

我希望能夠添加類似:

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

不過,我似乎無法找到一種方法來訪問請求在ModelForm中。

我的觀點是,像這樣:

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 

但我得到的錯誤: init()得到了一個意想不到的關鍵字參數'place_user'

對此有何意見?或者任何人都可以想象一種方法來過濾視圖中的ModelChoiceField,而無需將我的請求傳遞給ModelForm?

回答

20

您需要在PlaceEventForm.__init__()方法從kwargs彈出鍵user,以防止它去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) 
+0

非常感謝!完美的作品。 – Brian 2011-04-27 18:13:43

+0

無法理解你如何做到這一點。 – 2013-07-21 02:34:29

+0

我完成了這個例子,讓我知道如果它仍然不清楚 – 2013-07-22 11:57:48

1

我在iPhone上,但是這麼做:

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

哇,這很難!沒有縮進支持!

0

要更新Yuji對Django 1.10+(包括Django 2.0+)的回答,請參見下面的示例(請注意更新的方法簽名)。 Yuji的建議方法將查詢集與其他業務邏輯一起保留在視圖中,並幫助保持任何形式類的清潔和直接。

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 

短:

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 
相關問題