视频加载失败

用户相关功能

1859 字
9 分钟
用户相关功能

【二】 登陆功能#

【1】需求分析#

【2】视图函数#

from django.shortcuts import render, HttpResponse
from django.urls import reverse
from utils.verify_code import create_verify_code
from user.forms import RegisterForm
from lib.CommonResponse import CommonResponse
from user.models import UserInfo
from django.contrib import auth
def login(request):
# 【1】判断当前请求方式为 POST 请求 并且当前请求是Ajax请求
if request.method == "POST" and request.is_ajax():
# 【2】从POST请求中获取得到 所有 POST 请求携带的数据
data = request.POST
username = data.get("username")
password = data.get("password")
confirm_password = data.get("confirm_password")
verify_code = data.get("verify_code")
if not all([username, password, confirm_password, verify_code]):
return CommonResponse(code=201, errors="请输入完整的信息!")
# 【3】从request的session中获取得到验证码
true_code = request.session.get("verify_code")
# 【4】校验当前输入的验证码和session中的验证码是否一致
if true_code.upper() != verify_code or not verify_code.upper():
return CommonResponse(code=201, errors="验证码错误!")
# 【5】校验用户名是否存在
if not UserInfo.objects.filter(username=username).exists() or not username:
return CommonResponse(code=202, errors="用户不存在!")
# 【6】校验两次密码是否一致
if password != confirm_password or not password or not confirm_password:
return CommonResponse(cpde=203, errors="两次密码不一致!")
# 【7】通过 auth 模块校验用户名和密码是否正确
user_obj = auth.authenticate(username=username, password=confirm_password)
if not user_obj:
return CommonResponse(code=204, errors="用户名或密码错误!")
# 【8】密码正确保存用户登录状态
auth.login(request, user_obj)
# 【9】返回响应数据
return CommonResponse(code=200, message=f"当前用户 {user_obj.username} 登录成功!", next_url=reverse("home"))
return render(request, "login.html", locals())
# 动态制作验证码图片
def get_verify_img(request):
# 调用工具类,获取验证码和验证码图片
code, img_data = create_verify_code()
# 将验证码添加到 request 中
request.session["verify_code"] = code
# 将图片二进制数据返回
return HttpResponse(img_data)

【3】前端页面#

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{# <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>#}
{# <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">#}
{# <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>#}
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap/js/bootstrap.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'js/sweetalert.min.js' %}"></script>
<script src="{% static 'plugins/layui/layui/layui.js' %}"></script>
<link rel="stylesheet" href="{% static 'plugins/layui/layui/css/layui.css' %}">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1 class="text-center">登陆界面</h1>
{# 登陆采用 form 表单提交用户输入的数据,没什么特别的意思,就是想多换几种方式而已 #}
{# <form action="" method="post"> #}
{# 也可以采用 注册遍历form对象的方式 #}
<form id="form_login">
{% csrf_token %}
{# 用户名输入框 #}
<div class="form-group">
<p>
<label for="inputUsername"></label>
用户名 : <input type="text" class="form-control" id="inputUsername" name="username"
placeholder="username">
</p>
</div>
{# 密码输入框 #}
<div class="form-group">
<p>
<label for="inputPassword"></label>
密码 : <input type="text" class="form-control" id="inputPassword" name="password"
placeholder="password">
</p>
</div>
{# 确认密码输入框 #}
<div class="form-group">
<p>
<label for="inputConfirmPassword"></label>
确认密码 : <input type="text" class="form-control" id="inputConfirmPassword"
name="confirm_password"
placeholder="confirm_password">
</p>
</div>
{# 验证码输入框 #}
<div class="form-group">
<p>
验证码 :
<div class="row">
{# 验证码输入框 #}
<div class="col-md-6">
<input type="text" class="form-control" name="verify_code">
</div>
{# 渲染图片验证码 #}
<div class="col-md-6">
{# 前端的 img 标签不只是能存放静态的图片文件路径,还能存动态的url链接 #}
{# <img src="{% static 'avatar/default.png' %}" alt="图片走丢了 ~ ~ ~ " style="width: 360px;height: 36px;"> #}
{# 后端返回的图片二进制数据可以正常渲染 #}
{# <img src="{% url 'verify_img' %}" alt="图片走丢了 ~ ~ ~ " style="width: 360px;height: 36px;"> #}
{# 动态渲染验证码图片 #}
<img src="{% url 'verify_img' %}" alt="图片走丢了 ~ ~ ~ "
style="width: 360px;height: 36px;" id="verify_code_img">
</div>
</div>
</p>
</div>
{# 用户提交数据按钮 #}
{# <input type="submit" class="btn btn-block btn-info"> #}
{# Ajax发送数据时点击的普通按钮,不触发 form 表单的自动刷新 #}
<input type="button" class="btn btn-block btn-info" id="btn_login" value="提交">
</form>
</div>
</div>
</div>
<script>
$(document).ready(
// 给验证码图片绑定点击事件,点击验证码图片时,自动触发刷新,返回新的验证码
// ajax 绑定点击事件方式之一:委托事件
$("#verify_code_img").on("click", function () {
// 【1】获取到当前 img 标签的 原来的 src 属性
let oldSrc = $(this).attr("src");
// 添加一个时间戳参数来确保 URL 不同
let timestamp = new Date().getTime();
// 【2】给当前旧src属性重新赋值 , 只要 src 的值和旧值不一致就会触发刷新
// 此方法 会不断的在路由后面拼接参数,导致路由太长
// $(this).attr("src", oldSrc + "?");
// 动态绑定当前时间戳作为参数
if (oldSrc.indexOf("?") > -1) {
// 删除 旧src属性中 原有的时间戳参数
let newSrc = oldSrc.replace(/\?.*/, '');
$(this).attr("src", `${newSrc}?t=${timestamp}`);
} else {
// 如果是第一次则新增一个时间戳
$(this).attr("src", `${$(this).attr("src")}?t=${timestamp}`);
}
}),
// 发送请求方式二:Ajax遍历取值
$("#btn_login").on("click", function () {
let data = {}
$.each($("#form_login").serializeArray(), function (index, dataDict) {
data[dataDict.name] = dataDict.value
});
// 将 csrf token 放入数据中传给后端做校验
data["csrfmiddlewaretoken"] = "{{ csrf_token }}";
$.ajax({
url: "",
type: "post",
data: data,
success: (response) => {
// 回调函数处理逻辑
if (response.code === 200) {
swal({
title: response.message,
icon: "success",
button: true,
}).then(() => {
window.location.href = response.next_url;
});
} else {
swal({
title: response.errors,
icon: "error",
button: true,
}).then(() => {
window.location.reload()
});
}
}
})
})
);
</script>
</body>
</html>

【4】路由映射#

from django.urls import path
from user.views import register, login, get_verify_img
urlpatterns = [
# 注册路由
path("register/", register, name="register"),
# 登陆路由
path("login/", login, name="login"),
# 获取验证码图片
path("verify_img/", get_verify_img, name="verify_img"),
]

【三】修改密码#

【1】需求分析#

【2】视图函数#

# 全局配置登陆跳转路由
LOGIN_URL = reversed("login")
# 修改密码接口
@login_required
def reset_password(request):
# 【1】确认当前请求为 POST 请求并且是 Ajax 请求
if request.method == "POST" and request.is_ajax():
# 【2】获取前端传递的参数
username = request.user.username
old_password = request.POST.get("old_password")
new_password = request.POST.get("new_password")
confirm_password = request.POST.get("confirm_password")
# 【3】确保前端传入的参数有值
if not all([old_password, new_password, confirm_password]):
return CommonResponse(code=201, errors="请补齐参数!")
# 【4】确保两次密码存在并且一致
if new_password != confirm_password or not new_password or not confirm_password:
return CommonResponse(code=202, errors="两次输入的密码不一致!")
# 【5】通过 auth 模块校验原密码是否一致
old_password_is_right = auth.authenticate(username=username, password=old_password)
if not old_password_is_right:
return CommonResponse(code=203, errors="原密码输入错误!")
# 【6】参数都正确,原密码正确,修改密码
request.user.set_password(confirm_password)
# 不要忘了 save 保存,否则不生效
request.user.save()
# 【7】退出当前登录用户,清除已经登录用户的数据
auth.logout(request)
# 【8】返回前端信息
return CommonResponse(code=200, message=f"用户 {username} 密码修改成功!", next_url=reverse("login"))

【3】前端页面#

(1)触发按钮#

{# 根据下面模态框中的属性弹出指定的模态框 #}
<li><a href="" data-toggle="modal" data-target=".bs-example-modal-lg">修改密码</a></li>

(2)模态框#

{# 修改密码模态框开始 #}
<div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
{# 右上角关闭模态框的 x #}
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
{# 大标题 : 修改密码页面 #}
<h4 class="modal-title text-center" id="myLargeModalLabel">修改密码</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6 col-md-offset-3">
{# 定义form表单,但是仍然不走 form 表单提交数据,而是使用ajax #}
<form id="reset_password_form">
<div class="form-group">
<label for="inputUsername">用户名 : </label>
<input type="text" class="form-control" name="username" id="inputUsername"
value="{{ request.user.username }}" disabled>
</div>
<div class="form-group">
<label for="inputOldPassword">旧密码 : </label>
<input type="text" class="form-control" name="old_password" id="inputOldPassword"
placeholder="old_password">
</div>
<div class="form-group">
<label for="inputNewPassword">新密码 : </label>
<input type="text" class="form-control" name="new_password" id="inputNewPassword"
placeholder="new_password">
</div>
<div class="form-group">
<label for="inputConfirmPassword">确认密码 : </label>
<input type="text" class="form-control" name="confirm_password"
id="inputConfirmPassword"
placeholder="confirm_password">
</div>
{# 定义点击修改按钮 #}
<div class="form-group">
<input type="button" class="btn btn-warning btn-block" value="确认修改"
id="btn_reset_password">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{# 修改密码模态框结束 #}

(3)Ajax请求#

// 修改密码按钮点击事件
$("#btn_reset_password").on("click", function () {
// 使用 sweetalert 的弹框确认事件
swal({
title: "修改密码操作不可逆!",
text: "一旦密码被修改,无法找回原密码,确认修改吗?",
icon: "warning",
buttons: true,
dangerMode: true,
}).then((willReset) => {
// 判断用户是否点击了确认按钮
if (willReset) {
let data = {}
$.each($("#reset_password_form").serializeArray(), function (index, dataDict) {
data[dataDict.name] = dataDict.value
})
data["csrfmiddlewaretoken"] = "{{ csrf_token }}"
$.ajax({
url: "{% url 'reset_password' %}",
type: "post",
data: data,
success: (response) => {
if (response.code === 200) {
swal({
title: response.message,
icon: "success",
button: true,
}).then(() => {
window.location.href = response.next_url;
});
} else {
swal({
title: response.errors,
icon: "error",
button: true,
}).then(() => {
window.location.reload()
});
}
}
})
} else {
swal("好好想一想哦 ~ ~ ~ ");
}
});
})

【4】路由映射#

【四】注销登录#

【1】需求分析#

【2】视图函数#

@login_required
def logout(request):
auth.logout(request)
return redirect("login")

【3】前端页面#

  • 无前端页面
<li><a href="{% url 'logout' %}">注销登陆</a></li>

【4】路由映射#

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
Profile Image of the Author
Dream
Hello, I'm Dream.
公告
欢迎来到我的博客!爱学习爱进步。
分类
标签
最新动态
站点统计
文章
300
分类
5
标签
26
总字数
640,882
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Vercel
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录