2011-04-27 34 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 
相关问题