代码标注

LXY_branch
lxy 5 months ago
parent 5b19fddbac
commit fc3bfc45e6

@ -1,52 +1,52 @@
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 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# 导入当前应用下的BlogUser模型自定义用户模型
class BlogUserCreationForm(forms.ModelForm):
class BlogUserCreationForm(forms.ModelForm): # 定义两个密码字段使用PasswordInput小部件隐藏输入
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# 关联的模型是BlogUser
fields = ('email',) # 表单中显示的字段(仅邮箱,密码单独定义)
def clean_password2(self):
def clean_password2(self):# 验证两个密码是否一致
# Check that the two password entries match
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"))
raise forms.ValidationError(_("passwords do not match"))# 密码不一致时抛出错误
return password2
def save(self, commit=True):
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()
user.source = 'adminsite'# 标记用户来源为“后台管理”
user.save()# 提交到数据库
return user
class BlogUserChangeForm(UserChangeForm):
class Meta:
model = BlogUser
fields = '__all__'
field_classes = {'username': UsernameField}
model = BlogUser # 关联的模型是BlogUser
fields = '__all__'# 显示模型的所有字段
field_classes = {'username': UsernameField}# 为用户名字段指定类保持Django原生逻辑
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
super().__init__(*args, **kwargs)# 调用父类的初始化方法
class BlogUserAdmin(UserAdmin):
form = BlogUserChangeForm
add_form = BlogUserCreationForm
form = BlogUserChangeForm# 指定修改用户时使用的表单
add_form = BlogUserCreationForm# 指定创建用户时使用的表单
list_display = (
'id',
'nickname',
@ -55,5 +55,5 @@ class BlogUserAdmin(UserAdmin):
'last_login',
'date_joined',
'source')
list_display_links = ('id', 'username')
ordering = ('-id',)
list_display_links = ('id', 'username')# 列表页中可点击跳转的字段
ordering = ('-id',)# 列表页的排序方式按ID倒序

@ -1,5 +1,5 @@
from django.apps import AppConfig
from django.apps import AppConfig#导入 Django 框架中用于应用配置的 AppConfig 类,这是 Django 应用配置的核心类
class AccountsConfig(AppConfig):
name = 'accounts'
class AccountsConfig(AppConfig):#定义 AccountsConfig 类,继承自 AppConfig用于对 accounts 应用进行自定义配置
name = 'accounts'#指定该应用的名称为 accountsDjango 会通过这个名称来识别和管理该应用

@ -15,7 +15,7 @@ class LoginForm(AuthenticationForm):
attrs={'placeholder': "username", "class": "form-control"})
self.fields['password'].widget = widgets.PasswordInput(
attrs={'placeholder': "password", "class": "form-control"})
#自定义登录表单在__init__方法中设置username文本输入占位符、form-control样式和password密码输入占位符、form-control样式字段的前端显示样式。
class RegisterForm(UserCreationForm):
def __init__(self, *args, **kwargs):
@ -29,17 +29,17 @@ class RegisterForm(UserCreationForm):
attrs={'placeholder': "password", "class": "form-control"})
self.fields['password2'].widget = widgets.PasswordInput(
attrs={'placeholder': "repeat password", "class": "form-control"})
#__init__方法中设置username文本输入、email邮箱输入、password1和password2密码输入字段的占位符与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
#clean_email方法验证邮箱是否已被注册若存在则抛出“邮箱已存在”的验证错误
class Meta:
model = get_user_model()
fields = ("username", "email")
#Meta类指定关联模型为自定义用户模型表单字段包含username和email
class ForgetPasswordForm(forms.Form):
new_password1 = forms.CharField(
@ -81,7 +81,7 @@ class ForgetPasswordForm(forms.Form):
}
),
)
#定义new_password1新密码密码输入、new_password2确认密码密码输入、email邮箱文本输入、code验证码文本输入字段均设置form-control样式和占位符。
def clean_new_password2(self):
password1 = self.data.get("new_password1")
password2 = self.data.get("new_password2")
@ -90,7 +90,7 @@ class ForgetPasswordForm(forms.Form):
password_validation.validate_password(password2)
return password2
# clean_new_password2方法验证两次新密码是否一致并对密码进行有效性校验
def clean_email(self):
user_email = self.cleaned_data.get("email")
if not BlogUser.objects.filter(
@ -100,6 +100,7 @@ class ForgetPasswordForm(forms.Form):
raise ValidationError(_("email does not exist"))
return user_email
# clean_email方法验证邮箱是否已注册基于BlogUser模型未注册则抛出“邮箱不存在”的验证错误
def clean_code(self):
code = self.cleaned_data.get("code")
error = utils.verify(
@ -109,9 +110,10 @@ class ForgetPasswordForm(forms.Form):
if error:
raise ValidationError(error)
return code
#clean_code方法调用工具方法utils.verify验证验证码有效性无效则抛出错误
class ForgetPasswordCodeForm(forms.Form):
email = forms.EmailField(
label=_('Email'),
)
#仅包含email字段邮箱输入用于忘记密码流程中验证邮箱的步骤

@ -8,28 +8,29 @@ from djangoblog.utils import get_current_site
# Create your models here.
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)
source = models.CharField(_('create source'), max_length=100, blank=True)
class BlogUser(AbstractUser):#自定义用户模型BlogUser继承自Django内置的AbstractUser可扩展的用户抽象类
nickname = models.CharField(_('nick name'), max_length=100, blank=True)#定义nickname字段字符类型支持国际化翻译最大长度100可为空。
creation_time = models.DateTimeField(_('creation time'), default=now)#定义creation_time字段日期时间类型默认值为当前时间now方法
last_modify_time = models.DateTimeField(_('last modify time'), default=now)#定义last_modify_time字段日期时间类型默认值为当前时间。
source = models.CharField(_('create source'), max_length=100, blank=True)#定义source字段字符类型记录用户创建来源最大长度100可为空。
def get_absolute_url(self):
return reverse(
'blog:author_detail', kwargs={
'author_name': self.username})
'author_name': self.username})#定义获取用户详情页绝对URL的方法通过reverse反向解析路由blog:author_detail传递username参数。
def __str__(self):
return self.email
return self.email#定义对象的字符串表示方法返回用户的email
def get_full_url(self):
site = get_current_site().domain
url = "https://{site}{path}".format(site=site,
path=self.get_absolute_url())
return url
return url#定义获取带域名的完整URL方法结合当前站点域名和get_absolute_url生成完整链接
class Meta:
ordering = ['-id']
verbose_name = _('user')
verbose_name_plural = verbose_name
get_latest_by = 'id'
ordering = ['-id']#查询结果按id倒序排列
verbose_name = _('user')#模型的单数显示名称(支持国际化)
verbose_name_plural = verbose_name#模型的复数显示名称与单数一致。
get_latest_by = 'id'#指定按id获取最新记录

@ -53,7 +53,7 @@ class AccountTest(TestCase):
article.save()
response = self.client.get(article.get_admin_url())
self.assertEqual(response.status_code, 200)
self.assertEqual(response.status_code, 200)#测试管理员账号登录后台功能:创建超级用户,验证登录状态和后台页面访问状态
def test_validate_register(self):
self.assertEquals(
@ -116,7 +116,7 @@ class AccountTest(TestCase):
self.assertIn(response.status_code, [301, 302, 200])
response = self.client.get(article.get_admin_url())
self.assertIn(response.status_code, [301, 302, 200])
self.assertIn(response.status_code, [301, 302, 200])#测试用户注册流程:验证注册前后用户数量变化,邮箱验证链接的有效性,以及注册后用户权限、文章发布等功能
def test_verify_email_code(self):
to_email = "admin@admin.com"
@ -128,7 +128,7 @@ class AccountTest(TestCase):
self.assertEqual(err, None)
err = utils.verify("admin@123.com", code)
self.assertEqual(type(err), str)
self.assertEqual(type(err), str)#测试邮箱验证码功能:验证有效邮箱和无效邮箱的验证码校验结果
def test_forget_password_email_code_success(self):
resp = self.client.post(
@ -137,7 +137,7 @@ class AccountTest(TestCase):
)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.content.decode("utf-8"), "ok")
self.assertEqual(resp.content.decode("utf-8"), "ok")#测试忘记密码的邮箱验证码发送:分别验证成功和失败场景(如邮箱错误)的接口响应
def test_forget_password_email_code_fail(self):
resp = self.client.post(
@ -203,5 +203,5 @@ class AccountTest(TestCase):
data=data
)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.status_code, 200)#测试忘记密码流程:成功场景:验证密码修改后是否生效;失败场景:验证不存在用户、验证码错误时的接口响应

@ -9,20 +9,21 @@ app_name = "accounts"
urlpatterns = [re_path(r'^login/$',
views.LoginView.as_view(success_url='/'),
name='login',
kwargs={'authentication_form': LoginForm}),
kwargs={'authentication_form': LoginForm}),#登录路由对应LoginView用LoginForm表单成功重定向/
re_path(r'^register/$',
views.RegisterView.as_view(success_url="/"),
name='register'),
name='register'),#注册路由对应RegisterView成功重定向/。
re_path(r'^logout/$',
views.LogoutView.as_view(),
name='logout'),
name='logout'),#登出路由对应LogoutView。
path(r'account/result.html',
views.account_result,
name='result'),
name='result'),#结果页路由对应account_result视图
re_path(r'^forget_password/$',
views.ForgetPasswordView.as_view(),
name='forget_password'),
name='forget_password'),#忘记密码路由对应ForgetPasswordView
re_path(r'^forget_password_code/$',
views.ForgetPasswordEmailCode.as_view(),
name='forget_password_code'),
name='forget_password_code'),#忘记密码验证码路由对应ForgetPasswordEmailCode
]

@ -2,7 +2,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
class EmailOrUsernameModelBackend(ModelBackend):
class EmailOrUsernameModelBackend(ModelBackend):#自定义Django认证后端支持用户名或邮箱两种方式登录。
"""
允许使用用户名或邮箱登录
"""
@ -18,9 +18,10 @@ class EmailOrUsernameModelBackend(ModelBackend):
return user
except get_user_model().DoesNotExist:
return None
#核心认证逻辑:判断输入是否为邮箱(含@分别用邮箱或用户名查询用户验证密码后返回用户对象若用户不存在则返回None。
def get_user(self, username):
try:
return get_user_model().objects.get(pk=username)
except get_user_model().DoesNotExist:
return None
#根据用户ID主键查询用户不存在则返回None用于Django认证系统的用户查询环节

@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from djangoblog.utils import send_email
_code_ttl = timedelta(minutes=5)
_code_ttl = timedelta(minutes=5)#验证码有效期设置为5分钟。
def send_verify_email(to_mail: str, code: str, subject: str = _("Verify Email")):
@ -44,6 +44,6 @@ def set_code(email: str, code: str):
cache.set(email, code, _code_ttl.seconds)
def get_code(email: str) -> typing.Optional[str]:
def get_code(email: str) -> typing.Optional[str]:#从缓存中获取指定邮箱对应的验证码
"""获取code"""
return cache.get(email)

@ -33,7 +33,7 @@ logger = logging.getLogger(__name__)
class RegisterView(FormView):
form_class = RegisterForm
template_name = 'account/registration_form.html'
template_name = 'account/registration_form.html'#处理用户注册逻辑指定表单类RegisterForm和模板account/registration_form.html。
@method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
@ -77,11 +77,11 @@ class RegisterView(FormView):
else:
return self.render_to_response({
'form': form
})
})#form_valid方法中保存用户并设置为非活跃状态生成邮箱验证链接并发送验证邮件最后重定向到结果页。
class LogoutView(RedirectView):
url = '/login/'
url = '/login/'#处理用户登出,登出后重定向到/login/
@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
@ -90,7 +90,7 @@ class LogoutView(RedirectView):
def get(self, request, *args, **kwargs):
logout(request)
delete_sidebar_cache()
return super(LogoutView, self).get(request, *args, **kwargs)
return super(LogoutView, self).get(request, *args, **kwargs)#get方法中调用logout登出用户删除侧边栏缓存后完成重定向
class LoginView(FormView):
@ -113,8 +113,7 @@ class LoginView(FormView):
redirect_to = '/'
kwargs['redirect_to'] = redirect_to
return super(LoginView, self).get_context_data(**kwargs)
return super(LoginView, self).get_context_data(**kwargs)#处理用户登录逻辑指定表单类LoginForm、模板account / login.html和成功后重定向地址 /
def form_valid(self, form):
form = AuthenticationForm(data=self.request.POST, request=self.request)
@ -130,7 +129,7 @@ class LoginView(FormView):
else:
return self.render_to_response({
'form': form
})
})#form_valid方法中验证表单登录用户并根据“记住我”选项设置会话过期时间
def get_success_url(self):
@ -139,7 +138,7 @@ class LoginView(FormView):
url=redirect_to, allowed_hosts=[
self.request.get_host()]):
redirect_to = self.success_url
return redirect_to
return redirect_to#get_success_url方法处理登录后的重定向地址确保其安全性
def account_result(request):
@ -147,7 +146,7 @@ def account_result(request):
id = request.GET.get('id')
user = get_object_or_404(get_user_model(), id=id)
logger.info(type)
logger.info(type)#处理注册和邮箱验证的结果逻辑根据type参数区分场景
if user.is_active:
return HttpResponseRedirect('/')
if type and type in ['register', 'validation']:
@ -177,7 +176,7 @@ def account_result(request):
class ForgetPasswordView(FormView):
form_class = ForgetPasswordForm
template_name = 'account/forget_password.html'
template_name = 'account/forget_password.html'#处理忘记密码逻辑指定表单类ForgetPasswordForm和模板account/forget_password.html
def form_valid(self, form):
if form.is_valid():
@ -186,10 +185,10 @@ class ForgetPasswordView(FormView):
blog_user.save()
return HttpResponseRedirect('/login/')
else:
return self.render_to_response({'form': form})
return self.render_to_response({'form': form})#form_valid方法中验证表单后重置用户密码并重定向到登录页
class ForgetPasswordEmailCode(View):
class ForgetPasswordEmailCode(View):# 处理忘记密码的邮箱验证码发送逻辑
def post(self, request: HttpRequest):
form = ForgetPasswordCodeForm(request.POST)
@ -201,4 +200,4 @@ class ForgetPasswordEmailCode(View):
utils.send_verify_email(to_email, code)
utils.set_code(to_email, code)
return HttpResponse("ok")
return HttpResponse("ok")# post方法中验证邮箱表单生成并发送验证码将验证码存入缓存后返回成功标识

Loading…
Cancel
Save