如何在表单的clean()方法中访问请求对象或其他变量?

111 投票
12 回答
77236 浏览
提问于 2025-04-15 12:33

我想在一个表单的清理方法中使用请求的用户信息,但我该怎么获取请求对象呢?我可以修改这个清理方法,让它接受一些变量输入吗?

12 个回答

36

更新于2011年10月25日: 现在我使用的是动态创建的类,而不是方法,因为Django 1.3在其他情况下会出现一些奇怪的问题。

class MyModelAdmin(admin.ModelAdmin):
    form = MyCustomForm
    def get_form(self, request, obj=None, **kwargs):
        ModelForm = super(MyModelAdmin, self).get_form(request, obj, **kwargs)
        class ModelFormWithRequest(ModelForm):
            def __new__(cls, *args, **kwargs):
                kwargs['request'] = request
                return ModelForm(*args, **kwargs)
        return ModelFormWithRequest

接着,按照下面的方式重写 MyCustomForm.__init__

class MyCustomForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(MyCustomForm, self).__init__(*args, **kwargs)

这样,你就可以在 ModelForm 的任何方法中通过 self.request 来访问请求对象。

47

如果你在使用基于类的视图,而不是基于函数的视图,那么在你的编辑视图中,可以重写get_form_kwargs。下面是一个自定义的创建视图(CreateView)的示例代码:

from braces.views import LoginRequiredMixin

class MyModelCreateView(LoginRequiredMixin, CreateView):
    template_name = 'example/create.html'
    model = MyModel
    form_class = MyModelForm
    success_message = "%(my_object)s added to your site."

    def get_form_kwargs(self):
        kw = super(MyModelCreateView, self).get_form_kwargs()
        kw['request'] = self.request # the trick!
        return kw

    def form_valid(self):
        # do something

上面的视图代码会让request作为一个关键字参数传递给表单的__init__构造函数。因此在你的ModelForm中,你可以这样做:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        # important to "pop" added kwarg before call to parent's constructor
        self.request = kwargs.pop('request')
        super(MyModelForm, self).__init__(*args, **kwargs)
183

Ber的回答——把它存储在线程局部变量中——其实是个很糟糕的主意。这样做完全没有必要。

一个更好的方法是重写表单的 __init__ 方法,增加一个额外的关键字参数 request。这样可以把请求存储在 表单 中,这样就能在需要的地方使用,并且可以在你的清理方法中访问它。

class MyForm(forms.Form):

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(MyForm, self).__init__(*args, **kwargs)


    def clean(self):
        ... access the request object via self.request ...

然后在你的视图中:

myform = MyForm(request.POST, request=request)

撰写回答