我试图request.user获取表单的clean方法,但是如何访问请求对象?我可以修改clean方法以允许变量输入吗?
Dan*_*man 147
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 ...
Run Code Online (Sandbox Code Playgroud)
在你看来:
myform = MyForm(request.POST, request=request)
Run Code Online (Sandbox Code Playgroud)
Chr*_*att 31
更新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
Run Code Online (Sandbox Code Playgroud)
然后覆盖MyCustomForm.__init__
如下:
class MyCustomForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(MyCustomForm, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
然后,您可以从任何方法来访问请求对象ModelForm
用self.request
.
Jos*_*mit 27
对于它的价值,如果您使用基于类的视图而不是基于函数的视图,请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
Run Code Online (Sandbox Code Playgroud)
上面的视图代码将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)
Run Code Online (Sandbox Code Playgroud)
Ber*_*Ber 17
通常的方法是使用中间件将请求对象存储在线程局部引用中.然后,您可以从应用程序的任何位置访问它,包括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
Run Code Online (Sandbox Code Playgroud)
按照Django文档中的描述注册此中间件
Fra*_*ant 12
对于Django管理员,在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
Run Code Online (Sandbox Code Playgroud)
我在自定义管理员时遇到了这个特殊问题.我希望根据特定管理员的凭据验证某个字段.
由于我不想修改视图以将请求作为参数传递给表单,以下是我所做的:
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
Run Code Online (Sandbox Code Playgroud)
小智 5
您不能总是使用此方法(及其可能不好的做法),但如果您只在一个视图中使用该表单,则可以将其范围限定在view方法本身中.
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")
Run Code Online (Sandbox Code Playgroud)
丹尼尔罗斯曼的答案仍然是最好的.但是,我会使用请求的第一个位置参数而不是关键字参数,原因如下:
最后,我会使用一个更独特的名称来避免覆盖现有变量.因此,我修改后的答案如下:
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 ...
Run Code Online (Sandbox Code Playgroud)