一、功能需求分析
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 %}
標簽。
注冊功能已經開發好了,所以頁面的上的立即注冊
{% 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"> <div class="form-item"> <input type="tel" 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 = 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('用戶賬戶格式不正確,請重新輸入') # 一定要return return account def clean(self): """ 校驗用戶名密碼,並實現登錄邏輯 :return: """ cleaned_data = super().clean() account = cleaned_data.get('account') password = cleaned_data.get('password') remember = cleaned_data.get('remember') # 登錄邏輯 user_queryset = User.objects.filter(Q(mobile=account)|Q(username=account)) if user_queryset: user = user_queryset.first() 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文件
$(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,否則為false let 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'), ]
# 修改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>