from django import forms from django.contrib.auth import get_user_model, password_validation 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 内置 AuthenticationForm)""" def __init__(self, *args, **kwargs): super(LoginForm, self).__init__(*args, **kwargs) # 自定义输入框样式 self.fields['username'].widget = widgets.TextInput( attrs={'placeholder': "username", "class": "form-control"}) self.fields['password'].widget = widgets.PasswordInput( attrs={'placeholder': "password", "class": "form-control"}) # ------------------------- 注册表单 ------------------------- class RegisterForm(UserCreationForm): """用户注册表单(继承 Django 自带 UserCreationForm)""" def __init__(self, *args, **kwargs): super(RegisterForm, self).__init__(*args, **kwargs) # 为每个字段自定义前端样式与提示文本 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): """检查邮箱是否已被注册""" 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): """用户通过邮箱重置密码的表单""" # 新密码输入 new_password1 = forms.CharField( label=_("New password"), widget=forms.PasswordInput( attrs={ "class": "form-control", 'placeholder': _("New password") } ), ) # 新密码确认输入 new_password2 = forms.CharField( label="确认密码", widget=forms.PasswordInput( attrs={ "class": "form-control", 'placeholder': _("Confirm password") } ), ) # 邮箱输入 email = forms.EmailField( label='邮箱', 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): """验证两次输入的新密码是否一致,并校验密码强度""" password1 = self.data.get("new_password1") password2 = self.data.get("new_password2") if password1 and password2 and password1 != password2: raise ValidationError(_("passwords do not match")) # 两次密码不一致 password_validation.validate_password(password2) # 使用Django内置规则验证密码强度 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: # utils.verify 返回错误信息时表示验证失败 raise ValidationError(error) return code # ------------------------- 验证码邮箱发送表单 ------------------------- class ForgetPasswordCodeForm(forms.Form): """发送邮箱验证码表单,仅校验邮箱格式""" email = forms.EmailField( label=_('Email'), )