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