用户登录登出功能实现
一、功能需求分析
1. 登录退出功能分析
- 流程图
- 功能
- 登录页面
- 登录功能
- 退出功能
二、登录页面
1. 接口设计
- 接口说明
类目 | 说明 |
---|---|
请求方法 | GET |
url定义 | /user/login/ |
参数格式 | 无参数 |
-
返回结果
登录页面
2.后端代码
- user/views.py代码:
from django.shortcuts import render
from django.views import View
# ....class LoginView(View):"""登录视图"""def get(self, request):return render(request, 'user/login.html')
- user/urls.py代码:
from django.urls import path, include
from . import views
app_name = 'user'urlpatterns = [path('register/', views.RegisterView.as_view(), name='register'),path('login/', views.LoginView.as_view(), name='login'),
]
3.前端页面代码
1.user/login.html
因为表单需要post请求,所以记得在页面使用{% csrf_token %}
标签。
注册功能已经开发好了,所以页面的上的立即注册
处的a标签href可以写好
{% extends 'base/base.html' %}
{% load static %}{% block title %}登录{% endblock title %}
{% block link %}<link rel="stylesheet" href="{% static 'css/user/auth.css' %}">
{% endblock link %}{% block main_start %}<!-- container start -->
<main id="container"><div class="login-contain"><div class="top-contain"><h4 class="please-login">请登录</h4><a href="{% url 'user:register' %}" class="register">立即注册 ></a></div><form action="" method="post" class="form-contain">{% csrf_token %}<div class="form-item"><input type="text" placeholder="请输入用户名或手机号" name="account" class="form-control" autocomplete="off"></div><div class="form-item"><input type="password" placeholder="请输入密码" name="password" class="form-control"></div><div class="form-item clearfix"><label><input type="checkbox" name="remember"><span>记住我</span></label><a href="javascript:void(0);" class="forget-password">忘记密码?</a></div><div class="form-login"><input type="submit" value="登录" class="login-btn"></div>{% csrf_token %}</form></div>
</main>
<!-- container end -->
{% endblock main_start %}
三、登录功能
1. 业务流程
- 判断用户名账号是否为空
- 判断密码是否为空,格式是否正确
- 判断账户与密码是否正确
2.接口设计
接口说明:
类目 | 说明 |
---|---|
请求方法 | POST |
url定义 | /user/login/ |
参数格式 | 表单参数 |
参数说明:
参数名 | 类型 | 是否必须 | 描述 |
---|---|---|---|
account | 字符串 | 是 | 用户输入的用户名 |
password | 字符串 | 是 | 用户输入的密码 |
remember | 字符串 | 否 | 用户是否选择免登录 |
返回结果:
{"errno": "0", "errmsg": "OK",
}
3.后端代码
- 视图 在user目录下的views.py文件中定义如下视图:
class LoginView(View):"""登录视图"""def get(self, request):return render(request, 'user/login.html')def post(self, request):form = LoginForm(data=request.POST, request=request)if form.is_valid():return json_response(errmsg='恭喜登录成功!')else:err_msg_list = []for item in form.errors.values():err_msg_list.append(item[0])err_msg_str = '/'.join(err_msg_list)return json_response(errno=Code.PARAMERR, errmsg=err_msg_str)
- 表单 在user目下的forms.py文件中定义如下表单:
class LoginForm(forms.Form):account = forms.CharField(error_messages={'required': '账户不能为空'})password = forms.CharField(max_length=20, min_length=6,error_messages={'max_length': '密码长度要小于20','min_length': '密码长度要大于6','require': '密码不能为空'})remember = forms.BooleanField(required=False)def __init__(self, *args, **kwargs):self.request = kwargs.pop('request', None)super().__init__(*args, **kwargs)def clean_account(self):"""校验用户账户:return:account"""account = self.cleaned_data.get('account')if not re.match(r'^1[3-9]\d{9}$', account) and (len(account)<5 or len(account)>20):raise forms.ValidationError('用户账户格式不正确,请重新输入')# 一定要returnreturn accountdef clean(self):"""校验用户名密码,并实现登录逻辑:return:"""cleaned_data = super().clean()account = cleaned_data.get('account')password = cleaned_data.get('password')remember = cleaned_data.get('remember')# 登录逻辑#Q 相当于 or,判断输入账户是是手机号或用户名user_queryset = User.objects.filter(Q(mobile=account)|Q(username=account))if user_queryset:user = user_queryset.first()#user.check_password()是框架自带的用来校验密码是否一致的方法if user.check_password(password):if remember:self.request.session.set_expiry(constants.USER_SESSION_EXPIRY)else:self.request.session.set_expiry(0)login(self.request, user)else:raise forms.ValidationError('用户名密码错误!')else:raise forms.ValidationError('用户账号不存在,请重新输入!')
- 在user文件加下创建constants.py文件定义如下常量
# 用户session信息过期时间 单位秒 默认14天
USER_SESSION_EXPIRY = 14*24*60*60
4.前端js代码
修改user/login.html中用户账户输入框input的name为account
。
在static/js/user/下创建login.js文件
js代码如下:
$(function () {let $loginBtn = $('.login-btn'); // 获取登录按钮元素$loginBtn.click(function (e) {e.preventDefault(); // 阻止默认提交// 1.校验账户let sAccount = $('input[name="account"]').val();if (sAccount === ''){message.showError('用户账户不能为空');return}if(!(/^\w{5,20}$/).test(sAccount) && !(/^1[3-9]\d{9}$/).test(sAccount)){message.showError('用户账户格式不正确,请求重新输入');return}// 2.校验用户输入密码let sPassword = $('input[name="password"]').val();if(sPassword === ''){message.showError('用户密码不能为空');return}// 3.获取用户是否勾选'记住我',勾选为true,否则为falselet bRemember = $('input[name="remember"]').is(':checked');// 4.发送ajax$.ajax({url: '/user/login/',data: {account: sAccount,password: sPassword,remember: bRemember},type: 'POST',dataType: 'json',success: function (res) {if(res.errno === '0'){message.showSuccess('恭喜, 登录成功!');setTimeout(function () {//注册成功之后重定向到打开登录页面之前的页面if(!document.referrer || document.referrer.includes('/user/login/') || document.referrer.includes('/user/register/')){window.location.href = '/'}else {window.location.href = document.referrer}}, 3000)}else{message.showError(res.errmsg)}},error: function (xhr, msg) {message.showError('服务器超时,请重试')}});});
});
四、登出功能
1.接口设计
接口说明:
类目 | 说明 |
---|---|
请求方法 | GET |
url定义 | /user/logou/ |
参数格式 | 无参数 |
2.后端代码
# 在user目录下的views.py文件中定义如下视图:
class LogoutView(View):"""登出视图"""def get(self, request):logout(request)return redirect(reverse('user:login'))
# 在urser目录下的urls.py文件定义如下路由:
from django.urls import path
from . import views
app_name = 'user'urlpatterns = [path('register/', views.RegisterView.as_view(), name='register'),path('login/', views.LoginView.as_view(), name='login'),path('logout/', views.LogoutView.as_view(), name='logout'),
]
3.前端代码
# 修改templates/base/base.html中的header部分的代码如下
<header id="header"><div class="mw1200 header-contain clearfix"><!-- logo start --><h1 class="logo"><a href="javascript:void(0);" class="logo-title">Python</a></h1><!-- logo end --><!-- nav start --><nav class="nav"><ul class="menu"><li class="active"><a href="base.html">首页</a></li><li><a href="../course/course.html">在线课堂</a></li><li><a href="../doc/docDownload.html">下载文档</a></li><li><a href="search.html">搜索</a></li></ul></nav><!-- nav end --><!-- login start --><div class="login-box">{% if user.is_authenticated %}<div class="author"><i class="PyWhich py-user"></i><span>{{ user.username }}</span><ul class="author-menu">{% if user.is_staff %}<li><a href="javascript:void(0);">后台管理</a></li>{% endif %}<li><a href="{% url 'user:logout' %}">退出登录</a></li></ul></div>{% else %}<div><i class="PyWhich py-user"></i><span><a href="{% url 'user:login' %}" class="login">登录</a> / <a href="{% url 'user:register' %}"class="reg">注册</a></span></div>{% endif %}</div><!-- login end --></div>
</header>