ZYY_branch
zyy 4 months ago
parent 2f820592de
commit f2ba999735

@ -1,59 +1,100 @@
from django import forms
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth.forms import UsernameField
from django.utils.translation import gettext_lazy as _
#django核心组件导入
from django import forms# Django 表单处理模块
from django.contrib.auth.admin import UserAdmin # Django 默认用户管理后台类
from django.contrib.auth.forms import UserChangeForm # 用户信息修改表单基类
from django.contrib.auth.forms import UsernameField# 用户名专用表单字段
from django.utils.translation import gettext_lazy as _ # 国际化翻译函数
# 本地应用导入
# Register your models here.
from .models import BlogUser
from .models import BlogUser # 导入自定义用户模型
class BlogUserCreationForm(forms.ModelForm):
password1 = forms.CharField(label=_('password'), widget=forms.PasswordInput)
password2 = forms.CharField(label=_('Enter password again'), widget=forms.PasswordInput)
"""
自定义用户创建表单(用于管理后台添加新用户)
继承自 ModelForm专门处理 BlogUser 模型的创建
"""
# 定义密码输入字段(需要输入两次以确保一致)
password1 = forms.CharField(label=_('password'), # 字段标签(支持国际化)
widget=forms.PasswordInput) # 密码输入控件
password2 = forms.CharField(label=_('Enter password again'), # 确认密码标签
widget=forms.PasswordInput) # 密码输入控件
class Meta:
model = BlogUser
fields = ('email',)
model = BlogUser# 关联的模型类
fields = ('email',)# 创建用户时显示的字段这里只显示email字段
def clean_password2(self):
"""
验证两次输入的密码是否一致
Django 表单验证方法方法名必须以 clean_ 开头
"""
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
password1 = self.cleaned_data.get("password1")# 获取第一次输入的密码
password2 = self.cleaned_data.get("password2")# 获取第二次输入的密码
# 如果两次密码不一致,抛出验证错误
if password1 and password2 and password1 != password2:
raise forms.ValidationError(_("passwords do not match"))
return password2
raise forms.ValidationError(_("passwords do not match"))# 错误信息(支持国际化)
return password2# 返回验证后的值
def save(self, commit=True):
"""
重写保存方法在保存用户前处理密码哈希
"""
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
user = super().save(commit=False) # 调用父类保存方法但不提交到数据库
user.set_password(self.cleaned_data["password1"]) # 对密码进行哈希加密
if commit:
user.source = 'adminsite'
user.save()
return user
user.source = 'adminsite' # 设置用户来源标记(表示通过管理后台创建)
user.save()# 保存到数据库
return user# 返回用户对象
class BlogUserChangeForm(UserChangeForm):
"""
自定义用户信息修改表单用于管理后台编辑用户
继承自 Django 自带的 UserChangeForm
"""
class Meta:
model = BlogUser
fields = '__all__'
field_classes = {'username': UsernameField}
model = BlogUser # 关联的模型类
fields = '__all__'# 显示所有字段
field_classes = {'username': UsernameField}# 指定用户名使用专用字段类型
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
"""
表单初始化方法
可以在这里对表单字段进行自定义设置
"""
super().__init__(*args, **kwargs) # 调用父类初始化方法
# 可以在这里添加自定义逻辑,如修改字段属性等
class BlogUserAdmin(UserAdmin):
form = BlogUserChangeForm
add_form = BlogUserCreationForm
"""
自定义用户管理后台配置
继承自 Django 自带的 UserAdmin
"""
# 指定使用的表单类
form = BlogUserChangeForm # 编辑用户时使用的表单
add_form = BlogUserCreationForm# 添加用户时使用的表单
# 管理后台列表页显示配置
list_display = (
'id',
'nickname',
'username',
'email',
'last_login',
'date_joined',
'source')
'id', # 用户ID
'nickname', # 用户昵称
'username',# 用户名
'email', # 电子邮箱
'last_login', # 最后登录时间
'date_joined', # 注册时间
'source')# 用户来源标记
# 设置哪些字段可以点击跳转到编辑页
list_display_links = ('id', 'username')
# 默认排序规则按ID降序排列
ordering = ('-id',)

@ -1,5 +1,11 @@
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts'
"""
Accounts 应用的配置类
功能
1. 定义应用名称 Django 内部识别
2. 可在此处覆盖 ready() 方法以注册信号等
"""
name = 'accounts'# 必须与项目中的应用目录名完全一致

@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from . import utils
from .models import BlogUser
# 登录表单继承自Django内置的AuthenticationForm
class LoginForm(AuthenticationForm):
def __init__(self, *args, **kwargs):
super(LoginForm, self).__init__(*args, **kwargs)
@ -16,11 +16,11 @@ class LoginForm(AuthenticationForm):
self.fields['password'].widget = widgets.PasswordInput(
attrs={'placeholder': "password", "class": "form-control"})
# 注册表单继承自Django内置的UserCreationForm
class RegisterForm(UserCreationForm):
def __init__(self, *args, **kwargs):
super(RegisterForm, self).__init__(*args, **kwargs)
# 自定义用户名、邮箱和密码字段的HTML属性
self.fields['username'].widget = widgets.TextInput(
attrs={'placeholder': "username", "class": "form-control"})
self.fields['email'].widget = widgets.EmailInput(
@ -29,18 +29,18 @@ class RegisterForm(UserCreationForm):
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"),
@ -51,7 +51,7 @@ class ForgetPasswordForm(forms.Form):
}
),
)
# 新密码字段2用于确认
new_password2 = forms.CharField(
label="确认密码",
widget=forms.PasswordInput(
@ -61,7 +61,7 @@ class ForgetPasswordForm(forms.Form):
}
),
)
# 邮箱字段
email = forms.EmailField(
label='邮箱',
widget=forms.TextInput(
@ -71,7 +71,7 @@ class ForgetPasswordForm(forms.Form):
}
),
)
# 验证码字段
code = forms.CharField(
label=_('Code'),
widget=forms.TextInput(
@ -81,16 +81,16 @@ class ForgetPasswordForm(forms.Form):
}
),
)
# 验证两次输入的密码是否一致,并检查密码强度
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)
password_validation.validate_password(password2)# 使用Django的密码验证器
return password2
# 验证邮箱是否已注册
def clean_email(self):
user_email = self.cleaned_data.get("email")
if not BlogUser.objects.filter(
@ -99,10 +99,10 @@ class ForgetPasswordForm(forms.Form):
# todo 这里的报错提示可以判断一个邮箱是不是注册过,如果不想暴露可以修改
raise ValidationError(_("email does not exist"))
return user_email
# 验证用户输入的验证码是否正确
def clean_code(self):
code = self.cleaned_data.get("code")
error = utils.verify(
error = utils.verify(# 调用工具函数验证验证码
email=self.cleaned_data.get("email"),
code=code,
)
@ -110,7 +110,7 @@ class ForgetPasswordForm(forms.Form):
raise ValidationError(error)
return code
# 忘记密码功能中的验证码发送表单(仅需邮箱字段)
class ForgetPasswordCodeForm(forms.Form):
email = forms.EmailField(
label=_('Email'),

@ -1,39 +1,39 @@
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.urls import reverse
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from blog.models import Article
from djangoblog.utils import get_current_site
# Create your models here.
class Comment(models.Model):
body = models.TextField('正文', max_length=300)
# 自定义用户模型继承Django内置的AbstractUser
class BlogUser(AbstractUser):
# 用户昵称(可选)
nickname = models.CharField(_('nick name'), max_length=100, blank=True)
# 账号创建时间(默认当前时间)
creation_time = models.DateTimeField(_('creation time'), default=now)
# 最后修改时间(默认当前时间)
last_modify_time = models.DateTimeField(_('last modify time'), default=now)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
verbose_name=_('author'),
on_delete=models.CASCADE)
article = models.ForeignKey(
Article,
verbose_name=_('article'),
on_delete=models.CASCADE)
parent_comment = models.ForeignKey(
'self',
verbose_name=_('parent comment'),
blank=True,
null=True,
on_delete=models.CASCADE)
is_enable = models.BooleanField(_('enable'),
default=False, blank=False, null=False)
class Meta:
ordering = ['-id']
verbose_name = _('comment')
verbose_name_plural = verbose_name
get_latest_by = 'id'
# 账号创建来源(如:网站注册/第三方登录等,可选)
source = models.CharField(_('create source'), max_length=100, blank=True)
# 获取用户详情页的绝对URL用于模板中的{% url %}反向解析)
def get_absolute_url(self):
return reverse(
'blog:author_detail', kwargs={
'author_name': self.username})
# 定义对象的字符串表示Admin后台和shell中显示
def __str__(self):
return self.body
return self.email
# 获取用户详情页的完整URL包含域名用于分享链接
def get_full_url(self):
site = get_current_site().domain# 获取当前站点域名
url = "https://{site}{path}".format(site=site,
path=self.get_absolute_url())
return url
# 元数据配置(模型级别的选项)
class Meta:
ordering = ['-id'] # 默认按ID降序排列
verbose_name = _('user') # 单数形式名称(后台显示)
verbose_name_plural = verbose_name# 复数形式名称(后台显示)
get_latest_by = 'id'# 指定最新记录的排序字段

Loading…
Cancel
Save