【发布时间】:2011-11-10 03:04:30
【问题描述】:
在我的 ModelForm 实现中,我想根据当前用户是否是超级用户来执行不同类型的验证检查。如何访问当前请求用户?
【问题讨论】:
标签: django django-admin
在我的 ModelForm 实现中,我想根据当前用户是否是超级用户来执行不同类型的验证检查。如何访问当前请求用户?
【问题讨论】:
标签: django django-admin
如果您使用基于类的视图 (CBV),则在表单构造函数中(例如在 get_forms_class 中)或 form_class 中传递额外的参数将不起作用,因为将显示 <form> object is not callable。
CBV 的解决方案是使用get_form_kwargs(),例如:
views.py:
class MyUpdateView(UpdateView):
model = MyModel
form_class = MyForm
# Sending user object to the form, to verify which fields to display/remove (depending on group)
def get_form_kwargs(self):
kwargs = super(MyUpdateView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
forms.py:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user') # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
super(MyForm, self).__init__(*args, **kwargs)
# If the user does not belong to a certain group, remove the field
if not self.user.groups.filter(name__iexact='mygroup').exists():
del self.fields['confidential']
【讨论】:
您可以在表单构造函数中将用户对象作为额外参数传递。
例如
f = MyForm(user=request.user)
构造函数看起来像:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user',None)
super(MyForm, self).__init__(*args, **kwargs)
然后根据需要在 clean_XX 表单中使用用户
【讨论】:
我的小补充,
我有一个需求,其中表单的模型选择字段之一依赖于request.user,我花了一段时间才考虑清楚。
这个想法是
模型表单类中需要有__init__方法,
并且您从__init__ 方法的参数中访问request 或其他参数,
queryset
代码示例
class CsvUploadForm(forms.Form):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(CsvUploadForm, self).__init__(*args, **kwargs)
self.fields['lists'].queryset = List.objects.filter(user=user)
lists = forms.ModelChoiceField(queryset=None, widget=forms.Select, required=True)
如您所见,lists 变量依赖于当前用户,可通过request 对象获得,因此我们将字段的queryset 设置为null,稍后从构造函数中动态分配.
看看上面代码中语句的顺序
你可以像这样从视图文件中传递用户变量
form = CsvUploadForm(user=request.user)
或与其他 POST、FILE 数据类似,如下所示
form = CsvUploadForm(request.POST, request.FILES, user=request.user)
【讨论】:
您可以在它自己的实例中使用实例属性来引用用户对象。
前; self.instance.user
class StatusForm(ModelForm):
# def __init__(self, *args, **kwargs):
# self.user = kwargs.pop('user', None)
# super(StatusForm, self).__init__(*args, **kwargs)
class Meta:
model = Status
fields = [
'user',
'content',
'image'
]
def clean_content(self):
content = self.cleaned_data.get("content", None)
if len(content) > 240:
raise ValidationError(f"Hey {self.instance.user.username}, the content is too long")
return content
【讨论】: