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

我正在尝试request.user为窗体的干净的方法,但我怎样才能访问请求对象? 我可以修改干净的方法,以允许variablesinput?

Ber的答案 – 存储在threadlocals – 是一个非常糟糕的主意。 绝对没有理由这样做。

更好的方法是覆盖表单的__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) 

UPDATED 10/25/2011 :我现在使用这个元类而不是方法,因为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 ModelFormMetaClass(ModelForm): def __new__(cls, *args, **kwargs): kwargs['request'] = request return ModelForm(*args, **kwargs) return ModelFormMetaClass 

然后重写MyCustomForm.__init__ ,如下所示:

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

然后可以使用self.requestModelForm任何方法访问请求对象。

如果您使用基于类的视图 ,而不是基于视图的function,则可以在编辑视图中重写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) 

通常的方法是使用中间件将请求对象存储在线程本地引用中。 那么你可以从你的应用程序中的任何地方访问它,包括Form.clean()方法。

改变Form.clean()方法的签名意味着你有你自己的,修改后的Django版本,这可能不是你想要的。

感谢中间件计数看起来像这样:

 import threading _thread_locals = threading.local() def get_current_request(): return getattr(_thread_locals, 'request', None) class ThreadLocals(object): """ Middleware that gets various objects from the request object and saves them in thread local storage. """ def process_request(self, request): _thread_locals.request = request 

按照Django文档中的描述注册这个中间件

对于Djangopipe理员,在Django 1.8

 class MyModelAdmin(admin.ModelAdmin): ... form = RedirectForm def get_form(self, request, obj=None, **kwargs): form = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs) form.request = request return form 

我在定制pipe理员时遇到了这个特殊的问题。 我想要根据特定pipe理员的凭据validation某个字段。

由于我不想修改视图来将请求作为parameter passing给表单,所以我做了以下操作:

 class MyCustomForm(forms.ModelForm): class Meta: model = MyModel def clean(self): # make use of self.request here class MyModelAdmin(admin.ModelAdmin): form = MyCustomForm def get_form(self, request, obj=None, **kwargs): ModelForm = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs) def form_wrapper(*args, **kwargs): a = ModelForm(*args, **kwargs) a.request = request return a return form_wrapper 

你不能总是使用这个方法(和它可能是不好的做法),但是如果你只在一个视图中使用表单,你可以在视图方法本身的范围内。

 def my_view(request): class ResetForm(forms.Form): password = forms.CharField(required=True, widget=forms.PasswordInput()) def clean_password(self): data = self.cleaned_data['password'] if not request.user.check_password(data): raise forms.ValidationError("The password entered does not match your account password.") return data if request.method == 'POST': form = ResetForm(request.POST, request.FILES) if form.is_valid(): return HttpResponseRedirect("/") else: form = ResetForm() return render_to_response(request, "reset.html") 

来自cheesebaker的新鲜奶酪@ pypi: django-requestprovider

Daniel Roseman的答案仍然是最好的。 但是,我会使用请求的第一个位置参数,而不是关键字参数有几个原因:

  1. 你不要冒着压倒同名的kwarg的危险
  2. 该请求是可选的,这是不正确的。 请求属性在这个上下文中不能是None。
  3. 您可以干净地将参数和kwargs传递给父类,而不必修改它们。

最后,我会使用更独特的名称来避免覆盖现有的variables。 因此,我的修改答案如下所示:

 class MyForm(forms.Form): def __init__(self, request, *args, **kwargs): self._my_request = request super(MyForm, self).__init__(*args, **kwargs) def clean(self): ... access the request object via self._my_request ... 

我有另外一个回答这个问题,根据你的要求,你要访问用户的表单干净的方法。 你可以试试这个。 View.py

 person=User.objects.get(id=person_id) form=MyForm(request.POST,instance=person) 

forms.py

 def __init__(self,*arg,**kwargs): self.instance=kwargs.get('instance',None) if kwargs['instance'] is not None: del kwargs['instance'] super(Myform, self).__init__(*args, **kwargs) 

现在,您可以在form.py中使用任何干净的方法来访问self.instance