Update views.py

master
p9xvr8cjz 1 month ago
parent 7c87cba014
commit ed5eb76a24

@ -32,25 +32,60 @@ logger = logging.getLogger(__name__)
# Create your views here.
class RegisterView(FormView):
"""
用户注册视图类继承自Django的FormView
处理用户注册的全流程表单展示数据验证用户创建邮件发送
"""
#ZXY: 指定使用的表单类
form_class = RegisterForm
#ZXY: 指定渲染的模板路径
template_name = 'account/registration_form.html'
@method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
"""
重写dispatch方法添加CSRF保护装饰器
CSRF保护防止跨站请求伪造攻击确保表单提交来自本站
Returns:
HttpResponse: 处理后的HTTP响应
"""
return super(RegisterView, self).dispatch(*args, **kwargs)
def form_valid(self, form):
"""
表单数据验证成功后的处理逻辑
这是注册流程的核心方法包含用户创建和邮件发送
Args:
form: 已验证通过的RegisterForm实例
Returns:
HttpResponseRedirect: 重定向到结果页面
"""
if form.is_valid():
#ZXY: 第一步:创建用户对象但不立即保存到数据库
#ZXY: save(False)表示只创建对象实例不执行数据库INSERT
user = form.save(False)
user.is_active = False
user.source = 'Register'
#ZXY: 第二步:设置用户状态和属性
user.is_active = False #ZXY: 邮箱验证前用户处于未激活状态,无法登录
user.source = 'Register' #ZXY: 记录注册来源,便于后续统计分析
#ZXY: 第三步:保存用户到数据库
#ZXY: save(True)表示立即执行数据库保存操作
user.save(True)
site = get_current_site().domain
#ZXY: 第四步:准备邮箱验证所需数据
site = get_current_site().domain #ZXY: 获取当前站点域名
#ZXY: 生成安全签名:对密钥+用户ID进行双重SHA256哈希防止篡改
sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
#ZXY: 开发环境下使用本地地址,生产环境使用真实域名
if settings.DEBUG:
site = '127.0.0.1:8000'
path = reverse('account:result')
site = '127.0.0.1:8000' #ZXY: 开发环境固定地址
# 第五步:构建邮箱验证链接
path = reverse('account:result') #ZXY: 生成结果页面的URL路径
url = "http://{site}{path}?type=validation&id={id}&sign={sign}".format(
site=site, path=path, id=user.id, sign=sign)
@ -64,141 +99,215 @@ class RegisterView(FormView):
如果上面链接无法打开请将此链接复制至浏览器
{url}
""".format(url=url)
#ZXY: 第七步:发送验证邮件
send_email(
emailto=[
user.email,
user.email, #ZXY: 收件人列表,这里只有注册用户
],
title='验证您的电子邮箱',
content=content)
title='验证您的电子邮箱', #ZXY: 邮件标题
content=content) #ZXY: 邮件正文内容
#ZXY: 步骤8重定向到注册结果页面
url = reverse('accounts:result') + \
'?type=register&id=' + str(user.id)
return HttpResponseRedirect(url)
else:
#ZXY: 表单验证失败,重新显示表单页
return self.render_to_response({
'form': form
})
class LogoutView(RedirectView):
url = '/login/'
"""
用户退出登录视图
功能处理用户退出清除session重定向到登录页
"""
url = '/login/' #ZXY: 退出后重定向的URL
@method_decorator(never_cache)
@method_decorator(never_cache) #ZXY: 禁止缓存,确保每次都是最新状态
def dispatch(self, request, *args, **kwargs):
return super(LogoutView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
logout(request)
delete_sidebar_cache()
"""
处理GET请求退出登录
"""
logout(request) #ZXY: Django内置的退出函数清除session
delete_sidebar_cache() #ZXY: 清除侧边栏缓存
return super(LogoutView, self).get(request, *args, **kwargs)
class LoginView(FormView):
form_class = LoginForm
template_name = 'account/login.html'
success_url = '/'
redirect_field_name = REDIRECT_FIELD_NAME
login_ttl = 2626560 # 一个月的时间
@method_decorator(sensitive_post_parameters('password'))
@method_decorator(csrf_protect)
@method_decorator(never_cache)
"""
用户登录视图
功能处理用户登录认证支持"记住我"功能
"""
form_class = LoginForm #ZXY: 登录表单
template_name = 'account/login.html' #ZXY: 登录页面模板
success_url = '/' #ZXY: 登录成功后的默认跳转页面
redirect_field_name = REDIRECT_FIELD_NAME #ZXY: 重定向字段名,默认为'next'
login_ttl = 2626560 #ZXY: "记住我"功能的session有效期一个月单位
@method_decorator(sensitive_post_parameters('password')) #ZXY: 敏感参数保护,不在错误报告中显示密码
@method_decorator(csrf_protect) #ZXY: CSRF保护
@method_decorator(never_cache) #ZXY: 禁止缓存
def dispatch(self, request, *args, **kwargs):
"""
添加安全装饰器的dispatch方法
"""
return super(LoginView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
"""
添加上下文数据主要是重定向URL
"""
redirect_to = self.request.GET.get(self.redirect_field_name)
if redirect_to is None:
redirect_to = '/'
redirect_to = '/' #ZXY: 默认重定向到首页
kwargs['redirect_to'] = redirect_to
return super(LoginView, self).get_context_data(**kwargs)
def form_valid(self, form):
"""
登录表单验证成功后的处理
"""
#ZXY: 使用Django内置的AuthenticationForm进行认证
form = AuthenticationForm(data=self.request.POST, request=self.request)
if form.is_valid():
delete_sidebar_cache()
logger.info(self.redirect_field_name)
delete_sidebar_cache() #ZXY: 清除侧边栏缓存
logger.info(self.redirect_field_name) #ZXY: 记录日志
#ZXY: 执行用户登录
auth.login(self.request, form.get_user())
#ZXY: 处理"记住我"功能
if self.request.POST.get("remember"):
#ZXY: 设置session过期时间为一个月
self.request.session.set_expiry(self.login_ttl)
return super(LoginView, self).form_valid(form)
# return HttpResponseRedirect('/')
#ZXY: return HttpResponseRedirect('/')
else:
#ZXY: 认证失败,重新显示表单
return self.render_to_response({
'form': form
})
def get_success_url(self):
"""
获取登录成功后的跳转URL
支持next参数指定的重定向
"""
redirect_to = self.request.POST.get(self.redirect_field_name)
#ZXY: 安全检查确保重定向URL在允许的host范围内
if not url_has_allowed_host_and_scheme(
url=redirect_to, allowed_hosts=[
self.request.get_host()]):
redirect_to = self.success_url
redirect_to = self.success_url #ZXY: 不安全的URL使用默认首页
return redirect_to
def account_result(request):
type = request.GET.get('type')
id = request.GET.get('id')
"""
账户操作结果页面视图函数
处理注册结果和邮箱验证结果展示
"""
type = request.GET.get('type') #ZXY: 操作类型register或validation
id = request.GET.get('id') #ZXY: 用户ID
user = get_object_or_404(get_user_model(), id=id) #ZXY: 获取用户对象不存在返回404
logger.info(type) #ZXY: 记录操作类型日志
user = get_object_or_404(get_user_model(), id=id)
logger.info(type)
#ZXY: 如果用户已激活,直接跳转到首页
if user.is_active:
return HttpResponseRedirect('/')
if type and type in ['register', 'validation']:
if type == 'register':
#ZXY: 注册成功页面
content = '''
恭喜您注册成功一封验证邮件已经发送到您的邮箱请验证您的邮箱后登录本站
'''
title = '注册成功'
else:
#ZXY: 邮箱验证处理
c_sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
sign = request.GET.get('sign')
#ZXY: 签名验证防止URL篡改
if sign != c_sign:
return HttpResponseForbidden()
return HttpResponseForbidden() #ZXY: 签名不匹配返回403禁止访问
#ZXY: 激活用户账号
user.is_active = True
user.save()
content = '''
恭喜您已经成功的完成邮箱验证您现在可以使用您的账号来登录本站
'''
title = '验证成功'
#ZXY: 渲染结果页面
return render(request, 'account/result.html', {
'title': title,
'content': content
})
else:
#ZXY: 无效的操作类型,跳转到首页
return HttpResponseRedirect('/')
class ForgetPasswordView(FormView):
form_class = ForgetPasswordForm
template_name = 'account/forget_password.html'
"""
忘记密码视图
功能处理用户密码重置
"""
form_class = ForgetPasswordForm #ZXY: 忘记密码表单
template_name = 'account/forget_password.html' #ZXY: 模板路径
def form_valid(self, form):
"""
表单验证成功后的密码重置逻辑
"""
if form.is_valid():
#ZXY: 根据邮箱查找用户
blog_user = BlogUser.objects.filter(email=form.cleaned_data.get("email")).get()
#ZXY: 使用Django的密码哈希函数设置新密码
blog_user.password = make_password(form.cleaned_data["new_password2"])
blog_user.save()
blog_user.save() #ZXY: 保存到数据库
#ZXY: 重定向到登录页面
return HttpResponseRedirect('/login/')
else:
#ZXY: 表单验证失败,重新显示表单
return self.render_to_response({'form': form})
class ForgetPasswordEmailCode(View):
"""
忘记密码邮箱验证码发送视图
功能接收邮箱地址发送密码重置验证码
"""
def post(self, request: HttpRequest):
"""
处理POST请求发送验证码邮件
"""
form = ForgetPasswordCodeForm(request.POST)
if not form.is_valid():
return HttpResponse("错误的邮箱")
to_email = form.cleaned_data["email"]
return HttpResponse("错误的邮箱") #ZXY: 表单验证失败
to_email = form.cleaned_data["email"] #ZXY: 获取邮箱地址
#ZXY: 生成6位验证码
code = generate_code()
#ZXY: 发送验证码邮件
utils.send_verify_email(to_email, code)
#ZXY: 将验证码存储到缓存5分钟有效期
utils.set_code(to_email, code)
return HttpResponse("ok")
return HttpResponse("ok") #ZXY: 返回成功响应

Loading…
Cancel
Save