用户登录登出功能实现

用户登录登出功能实现

一、功能需求分析

1. 登录退出功能分析

  1. 流程图
    在这里插入图片描述
  2. 功能
    1. 登录页面
    2. 登录功能
    3. 退出功能

二、登录页面

1. 接口设计

  1. 接口说明
类目 说明
请求方法 GET
url定义 /user/login/
参数格式 无参数
  1. 返回结果

    登录页面

2.后端代码

  1. 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')
  1. 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">立即注册 &gt;</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. 业务流程

  1. 判断用户名账号是否为空
  2. 判断密码是否为空,格式是否正确
  3. 判断账户与密码是否正确

2.接口设计

接口说明:

类目 说明
请求方法 POST
url定义 /user/login/
参数格式 表单参数

参数说明:

参数名 类型 是否必须 描述
account 字符串 用户输入的用户名
password 字符串 用户输入的密码
remember 字符串 用户是否选择免登录

返回结果:

{
    "errno": "0", 
 	"errmsg": "OK", 
}

3.后端代码

  1. 视图 在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)
  1. 表单 在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('用户账户格式不正确,请重新输入')
        # 一定要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')

        # 登录逻辑
        #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('用户账号不存在,请重新输入!')
  1. 在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代码如下:

扫描二维码关注公众号,回复: 9187209 查看本文章
$(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'),
]

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>

在这里插入图片描述

发布了12 篇原创文章 · 获赞 1 · 访问量 990

猜你喜欢

转载自blog.csdn.net/fksfdh/article/details/99598086