|
|
#shw 导入Django的表单模块
|
|
|
from django import forms
|
|
|
#shw 导入获取当前激活用户模型的函数
|
|
|
from django.contrib.auth import get_user_model, password_validation
|
|
|
#shw 导入Django内置的认证表单和用户创建表单
|
|
|
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
|
|
|
#shw 导入Django的验证错误类
|
|
|
from django.core.exceptions import ValidationError
|
|
|
#shw 导入Django的表单控件模块
|
|
|
from django.forms import widgets
|
|
|
#shw 导入Django的国际化和翻译工具
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
from . import utils
|
|
|
#shw 导入本地的BlogUser模型
|
|
|
from .models import BlogUser
|
|
|
|
|
|
|
|
|
class LoginForm(AuthenticationForm):
|
|
|
#shw 自定义登录表单,继承自Django的AuthenticationForm。
|
|
|
#shw 主要用于自定义前端显示的样式。
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
#shw 重写初始化方法,以自定义字段的控件属性。
|
|
|
super(LoginForm, self).__init__(*args, **kwargs) #shw 调用父类的初始化方法
|
|
|
#shw 自定义 'username' 字段的控件,添加placeholder和CSS类
|
|
|
self.fields['username'].widget = widgets.TextInput(
|
|
|
attrs={'placeholder': "username", "class": "form-control"})
|
|
|
#shw 自定义 'password' 字段的控件,添加placeholder和CSS类
|
|
|
self.fields['password'].widget = widgets.PasswordInput(
|
|
|
attrs={'placeholder': "password", "class": "form-control"})
|
|
|
|
|
|
|
|
|
class RegisterForm(UserCreationForm):
|
|
|
#shw 自定义注册表单,继承自Django的UserCreationForm。
|
|
|
#shw 增加了邮箱唯一性验证和前端样式自定义。
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
#shw 重写初始化方法,以自定义字段的控件属性。
|
|
|
super(RegisterForm, self).__init__(*args, **kwargs) #shw 调用父类的初始化方法
|
|
|
|
|
|
#shw 为各个字段添加Bootstrap风格的CSS类和placeholder
|
|
|
self.fields['username'].widget = widgets.TextInput(
|
|
|
attrs={'placeholder': "username", "class": "form-control"})
|
|
|
self.fields['email'].widget = widgets.EmailInput(
|
|
|
attrs={'placeholder': "email", "class": "form-control"})
|
|
|
self.fields['password1'].widget = widgets.PasswordInput(
|
|
|
attrs={'placeholder': "password", "class": "form-control"})
|
|
|
self.fields['password2'].widget = widgets.PasswordInput(
|
|
|
attrs={'placeholder': "repeat password", "class": "form-control"})
|
|
|
|
|
|
def clean_email(self):
|
|
|
#shw 自定义邮箱字段的验证方法,确保邮箱在系统中是唯一的。
|
|
|
email = self.cleaned_data['email'] #shw 获取清洗后的邮箱数据
|
|
|
#shw 检查数据库中是否已存在该邮箱
|
|
|
if get_user_model().objects.filter(email=email).exists():
|
|
|
raise ValidationError(_("email already exists")) #shw 如果存在,抛出验证错误
|
|
|
return email #shw 返回清洗后的邮箱
|
|
|
|
|
|
class Meta:
|
|
|
#shw Meta类用于配置表单与模型的关联
|
|
|
model = get_user_model() #shw 动态获取用户模型,而不是硬编码BlogUser,更具可复用性
|
|
|
fields = ("username", "email") #shw 指定注册表单中显示的字段
|
|
|
|
|
|
|
|
|
class ForgetPasswordForm(forms.Form):
|
|
|
#shw 忘记密码/重置密码表单,继承自基础的Form类。
|
|
|
#shw 它不直接与模型关联,用于处理通过邮箱和验证码重置密码的流程。
|
|
|
|
|
|
new_password1 = forms.CharField(
|
|
|
label=_("New password"),
|
|
|
widget=forms.PasswordInput(
|
|
|
attrs={
|
|
|
"class": "form-control",
|
|
|
'placeholder': _("New password")
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
new_password2 = forms.CharField(
|
|
|
label="确认密码", #shw 这里使用了中文硬编码,建议使用 _("Confirm password") 以支持国际化
|
|
|
widget=forms.PasswordInput(
|
|
|
attrs={
|
|
|
"class": "form-control",
|
|
|
'placeholder': _("Confirm password")
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
email = forms.EmailField(
|
|
|
label='邮箱', #shw 这里使用了中文硬编码,建议使用 _("Email")
|
|
|
widget=forms.TextInput(
|
|
|
attrs={
|
|
|
'class': 'form-control',
|
|
|
'placeholder': _("Email")
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
code = forms.CharField(
|
|
|
label=_('Code'),
|
|
|
widget=forms.TextInput(
|
|
|
attrs={
|
|
|
'class': 'form-control',
|
|
|
'placeholder': _("Code")
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
def clean_new_password2(self):
|
|
|
#shw 自定义验证方法,检查两次输入的新密码是否一致,并验证密码强度。
|
|
|
password1 = self.data.get("new_password1") #shw 从原始数据中获取密码1
|
|
|
password2 = self.data.get("new_password2") #shw 从原始数据中获取密码2
|
|
|
#shw 检查两次密码是否一致
|
|
|
if password1 and password2 and password1 != password2:
|
|
|
raise ValidationError(_("passwords do not match"))
|
|
|
#shw 使用Django内置的密码验证器来检查密码强度
|
|
|
password_validation.validate_password(password2)
|
|
|
|
|
|
return password2 #shw 返回验证通过的新密码
|
|
|
|
|
|
def clean_email(self):
|
|
|
#shw 自定义验证方法,检查输入的邮箱是否存在于数据库中。
|
|
|
user_email = self.cleaned_data.get("email") #shw 获取清洗后的邮箱
|
|
|
#shw 检查该邮箱是否已注册
|
|
|
if not BlogUser.objects.filter(
|
|
|
email=user_email
|
|
|
).exists():
|
|
|
#shwtodo 这里的报错提示可以判断一个邮箱是不是注册过,如果不想暴露可以修改
|
|
|
#shw 这是一个安全提示,直接告诉攻击者邮箱未注册可能会被利用。
|
|
|
raise ValidationError(_("email does not exist"))
|
|
|
return user_email #shw 返回清洗后的邮箱
|
|
|
|
|
|
def clean_code(self):
|
|
|
#shw 自定义验证方法,验证邮箱验证码是否正确。
|
|
|
code = self.cleaned_data.get("code") #shw 获取清洗后的验证码
|
|
|
#shw 调用工具函数验证邮箱和验证码是否匹配
|
|
|
error = utils.verify(
|
|
|
email=self.cleaned_data.get("email"),
|
|
|
code=code,
|
|
|
)
|
|
|
#shw 如果工具函数返回错误信息,则抛出验证错误
|
|
|
if error:
|
|
|
raise ValidationError(error)
|
|
|
return code #shw 返回验证通过的验证码
|
|
|
|
|
|
|
|
|
class ForgetPasswordCodeForm(forms.Form):
|
|
|
#shw 发送忘记密码验证码的表单。
|
|
|
#shw 它只包含一个邮箱字段,用于用户输入接收验证码的邮箱地址。
|
|
|
|
|
|
email = forms.EmailField(
|
|
|
label=_('Email'), #shw 邮箱字段,标签支持国际化
|
|
|
)
|