验证设计:表单还是视图?
Validation design: form or view?
我制作了一个 "edit profile" 表格,您可以在其中完成一件非常经典的事情:更改密码。
因此我有 3 个字段:旧密码、新密码和重新输入新密码。
问题出在设计上。
我首先检查输入的所有内容是否正常 ,格式为 clean
method:
def clean(self):
old = self.cleaned_data.get('old_password')
new1 = self.cleaned_data.get('new_password1')
new2 = self.cleaned_data.get('new_password2')
if old:
if not new1:
raise ValidationError(_(u'New password missing'))
if not new2:
raise ValidationError(_(u'New password missing'))
if new1 != new2:
raise ValidationError(_(u"The new password "
u"is not the same twice"))
return super(ProfileForm, self).clean()
在我的表单中,除非我破解,否则我无法访问当前登录的用户。
我的问题是关于设计的:是否更好地破解表单代码,然后在 form is_valid()
中更改密码,还是在 view form_valid()
方法中更好?
首先,Django 自带了一个 view and form 来更改密码],你应该尽可能使用它们。
如果你真的需要修改自己的视图和表单,我觉得在views form_valid()
方法中修改密码是可以的。
您可以将设置新密码的代码移动到表单上的一个方法中,然后在form_valid
方法中调用该方法。这种方法的缺点是您必须重写表单的 __init__
方法和视图的 get_form_kwargs
方法才能将用户传递给表单,这使它变得更加复杂。好处是你把功能封装在视图里了。
不要覆盖表单的 is_valid()
方法。此方法的目的是检查表单是否有效。您很少需要覆盖它。
Django 实际上有一个 built-in 表单用于更改用户密码,您可以参考。请参阅 SetPasswordForm
和 PasswordChangeForm
上的 https://github.com/django/django/blob/master/django/contrib/auth/forms.py。
不要更改is_valid()
方法中的密码,它仅用于验证。您可以重写表单的 __init__
来获取用户,并使用 save
方法来更改密码。
class MyForm(forms.Form):
def __init__(self, user, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.user = user
def save(self, commit=True):
password = self.cleaned_data["new_password1"]
self.user.set_password(password)
if commit:
self.user.save()
return self.user
密码更改操作应该在单独的方法中在表单中完成。以下是您需要的视图代码示例:
class MyView(TemplateView):
def post(self, request, *args, **kwargs):
form = MyForm(user=request.user, data=request.POST)
if form.is_valid():
form.save() # password updated
return redirect(<somehwere>)
# the password change has failed form validation
return self.render_to_response({})
为了回答您的问题,最好在表单中更改密码,而不是在视图中更改密码。在表单中执行数据操作(例如 ModelForm.save())是 Django 中相当常见的模式,并且大多数 Django 自己的代码也会更改表单中的模型数据。
这将更改模型数据的逻辑与视图分开,并使单元测试和推理变得更加容易(例如,您不需要依赖视图来测试更改密码操作)。
我制作了一个 "edit profile" 表格,您可以在其中完成一件非常经典的事情:更改密码。
因此我有 3 个字段:旧密码、新密码和重新输入新密码。
问题出在设计上。
我首先检查输入的所有内容是否正常 ,格式为 clean
method:
def clean(self):
old = self.cleaned_data.get('old_password')
new1 = self.cleaned_data.get('new_password1')
new2 = self.cleaned_data.get('new_password2')
if old:
if not new1:
raise ValidationError(_(u'New password missing'))
if not new2:
raise ValidationError(_(u'New password missing'))
if new1 != new2:
raise ValidationError(_(u"The new password "
u"is not the same twice"))
return super(ProfileForm, self).clean()
在我的表单中,除非我破解,否则我无法访问当前登录的用户。
我的问题是关于设计的:是否更好地破解表单代码,然后在 form is_valid()
中更改密码,还是在 view form_valid()
方法中更好?
首先,Django 自带了一个 view and form 来更改密码],你应该尽可能使用它们。
如果你真的需要修改自己的视图和表单,我觉得在views form_valid()
方法中修改密码是可以的。
您可以将设置新密码的代码移动到表单上的一个方法中,然后在form_valid
方法中调用该方法。这种方法的缺点是您必须重写表单的 __init__
方法和视图的 get_form_kwargs
方法才能将用户传递给表单,这使它变得更加复杂。好处是你把功能封装在视图里了。
不要覆盖表单的 is_valid()
方法。此方法的目的是检查表单是否有效。您很少需要覆盖它。
Django 实际上有一个 built-in 表单用于更改用户密码,您可以参考。请参阅 SetPasswordForm
和 PasswordChangeForm
上的 https://github.com/django/django/blob/master/django/contrib/auth/forms.py。
不要更改is_valid()
方法中的密码,它仅用于验证。您可以重写表单的 __init__
来获取用户,并使用 save
方法来更改密码。
class MyForm(forms.Form):
def __init__(self, user, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.user = user
def save(self, commit=True):
password = self.cleaned_data["new_password1"]
self.user.set_password(password)
if commit:
self.user.save()
return self.user
密码更改操作应该在单独的方法中在表单中完成。以下是您需要的视图代码示例:
class MyView(TemplateView):
def post(self, request, *args, **kwargs):
form = MyForm(user=request.user, data=request.POST)
if form.is_valid():
form.save() # password updated
return redirect(<somehwere>)
# the password change has failed form validation
return self.render_to_response({})
为了回答您的问题,最好在表单中更改密码,而不是在视图中更改密码。在表单中执行数据操作(例如 ModelForm.save())是 Django 中相当常见的模式,并且大多数 Django 自己的代码也会更改表单中的模型数据。
这将更改模型数据的逻辑与视图分开,并使单元测试和推理变得更加容易(例如,您不需要依赖视图来测试更改密码操作)。