|
|
# 导入Django表单模块
|
|
|
from django import forms
|
|
|
# 导入用户模型获取函数和密码验证工具
|
|
|
from django.contrib.auth import get_user_model, password_validation
|
|
|
# 导入Django内置认证表单
|
|
|
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
|
|
|
# 导入验证异常
|
|
|
from django.core.exceptions import ValidationError
|
|
|
# 导入表单控件
|
|
|
from django.forms import widgets
|
|
|
# 导入国际化翻译函数
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
# 导入工具函数
|
|
|
from . import utils
|
|
|
# 导入用户模型
|
|
|
from .models import BlogUser
|
|
|
|
|
|
|
|
|
class LoginForm(AuthenticationForm):
|
|
|
"""用户登录表单,继承自Django内置认证表单"""
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
"""初始化表单,自定义字段控件"""
|
|
|
# 调用父类初始化方法
|
|
|
super(LoginForm, self).__init__(*args, **kwargs)
|
|
|
# 自定义用户名字段控件:文本输入框,带占位符和CSS类
|
|
|
self.fields['username'].widget = widgets.TextInput(
|
|
|
attrs={
|
|
|
'placeholder': "username", # 输入框占位符文本
|
|
|
"class": "form-control" # CSS类名,用于样式
|
|
|
}
|
|
|
)
|
|
|
# 自定义密码字段控件:密码输入框,带占位符和CSS类
|
|
|
self.fields['password'].widget = widgets.PasswordInput(
|
|
|
attrs={
|
|
|
'placeholder': "password", # 输入框占位符文本
|
|
|
"class": "form-control" # CSS类名,用于样式
|
|
|
}
|
|
|
)
|
|
|
|
|
|
|
|
|
class RegisterForm(UserCreationForm):
|
|
|
"""用户注册表单,继承自Django内置用户创建表单"""
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
"""初始化表单,自定义所有字段的控件"""
|
|
|
# 调用父类初始化方法
|
|
|
super(RegisterForm, self).__init__(*args, **kwargs)
|
|
|
# 自定义用户名字段控件
|
|
|
self.fields['username'].widget = widgets.TextInput(
|
|
|
attrs={
|
|
|
'placeholder': "username", # 占位符:用户名
|
|
|
"class": "form-control" # CSS类
|
|
|
}
|
|
|
)
|
|
|
# 自定义邮箱字段控件
|
|
|
self.fields['email'].widget = widgets.EmailInput(
|
|
|
attrs={
|
|
|
'placeholder': "email", # 占位符:邮箱
|
|
|
"class": "form-control" # CSS类
|
|
|
}
|
|
|
)
|
|
|
# 自定义密码字段控件
|
|
|
self.fields['password1'].widget = widgets.PasswordInput(
|
|
|
attrs={
|
|
|
'placeholder': "password", # 占位符:密码
|
|
|
"class": "form-control" # CSS类
|
|
|
}
|
|
|
)
|
|
|
# 自定义密码确认字段控件
|
|
|
self.fields['password2'].widget = widgets.PasswordInput(
|
|
|
attrs={
|
|
|
'placeholder': "repeat password", # 占位符:重复密码
|
|
|
"class": "form-control" # CSS类
|
|
|
}
|
|
|
)
|
|
|
|
|
|
def clean_email(self):
|
|
|
"""清理和验证邮箱字段,确保邮箱唯一性"""
|
|
|
# 从已清理数据中获取邮箱
|
|
|
email = self.cleaned_data['email']
|
|
|
# 检查数据库中是否已存在该邮箱
|
|
|
if get_user_model().objects.filter(email=email).exists():
|
|
|
# 如果邮箱已存在,抛出验证错误
|
|
|
raise ValidationError(_("email already exists"))
|
|
|
# 返回验证通过的邮箱
|
|
|
return email
|
|
|
|
|
|
class Meta:
|
|
|
"""表单元数据配置"""
|
|
|
# 指定表单关联的模型
|
|
|
model = get_user_model()
|
|
|
# 表单包含的字段:用户名和邮箱
|
|
|
fields = ("username", "email")
|
|
|
|
|
|
|
|
|
class ForgetPasswordForm(forms.Form):
|
|
|
"""忘记密码重置表单"""
|
|
|
|
|
|
# 新密码字段1
|
|
|
new_password1 = forms.CharField(
|
|
|
label=_("New password"), # 字段标签:新密码
|
|
|
widget=forms.PasswordInput( # 使用密码输入控件
|
|
|
attrs={
|
|
|
"class": "form-control", # CSS类
|
|
|
'placeholder': _("New password") # 占位符:新密码
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
# 新密码字段2 - 确认密码
|
|
|
new_password2 = forms.CharField(
|
|
|
label="确认密码", # 字段标签:确认密码(硬编码中文)
|
|
|
widget=forms.PasswordInput( # 使用密码输入控件
|
|
|
attrs={
|
|
|
"class": "form-control", # CSS类
|
|
|
'placeholder': _("Confirm password") # 占位符:确认密码
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
# 邮箱字段
|
|
|
email = forms.EmailField(
|
|
|
label='邮箱', # 字段标签:邮箱(硬编码中文)
|
|
|
widget=forms.TextInput( # 使用文本输入控件
|
|
|
attrs={
|
|
|
'class': 'form-control', # CSS类
|
|
|
'placeholder': _("Email") # 占位符:邮箱
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
# 验证码字段
|
|
|
code = forms.CharField(
|
|
|
label=_('Code'), # 字段标签:验证码
|
|
|
widget=forms.TextInput( # 使用文本输入控件
|
|
|
attrs={
|
|
|
'class': 'form-control', # CSS类
|
|
|
'placeholder': _("Code") # 占位符:验证码
|
|
|
}
|
|
|
),
|
|
|
)
|
|
|
|
|
|
def clean_new_password2(self):
|
|
|
"""清理和验证密码确认字段"""
|
|
|
# 从原始数据中获取新密码1(不使用cleaned_data因为可能还未验证)
|
|
|
password1 = self.data.get("new_password1")
|
|
|
# 从原始数据中获取新密码2
|
|
|
password2 = self.data.get("new_password2")
|
|
|
# 检查两个密码是否存在且匹配
|
|
|
if password1 and password2 and password1 != password2:
|
|
|
# 如果不匹配,抛出验证错误
|
|
|
raise ValidationError(_("passwords do not match"))
|
|
|
# 使用Django内置密码验证器验证密码强度
|
|
|
password_validation.validate_password(password2)
|
|
|
# 返回验证通过的密码
|
|
|
return password2
|
|
|
|
|
|
def clean_email(self):
|
|
|
"""清理和验证邮箱字段,确保邮箱已注册"""
|
|
|
# 从已清理数据中获取邮箱
|
|
|
user_email = self.cleaned_data.get("email")
|
|
|
# 检查数据库中是否存在该邮箱的用户
|
|
|
if not BlogUser.objects.filter(email=user_email).exists():
|
|
|
# 安全提示:这里会暴露邮箱是否注册,可根据安全需求修改
|
|
|
# 如果邮箱不存在,抛出验证错误
|
|
|
raise ValidationError(_("email does not exist"))
|
|
|
# 返回验证通过的邮箱
|
|
|
return user_email
|
|
|
|
|
|
def clean_code(self):
|
|
|
"""清理和验证验证码字段"""
|
|
|
# 从已清理数据中获取验证码
|
|
|
code = self.cleaned_data.get("code")
|
|
|
# 调用工具函数验证验证码是否正确
|
|
|
error = utils.verify(
|
|
|
email=self.cleaned_data.get("email"), # 传入邮箱
|
|
|
code=code, # 传入验证码
|
|
|
)
|
|
|
# 如果验证返回错误信息
|
|
|
if error:
|
|
|
# 抛出验证错误
|
|
|
raise ValidationError(error)
|
|
|
# 返回验证通过的验证码
|
|
|
return code
|
|
|
|
|
|
|
|
|
class ForgetPasswordCodeForm(forms.Form):
|
|
|
"""获取忘记密码验证码的表单"""
|
|
|
|
|
|
# 邮箱字段
|
|
|
email = forms.EmailField(
|
|
|
label=_('Email'), # 字段标签:邮箱
|
|
|
) |