You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Django/forms.py

194 lines
7.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 导入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'), # 字段标签:邮箱
)