zoukankan      html  css  js  c++  java
  • Django项目: 4.用户登录登出功能

    用户登录登出功能

    一、功能需求分析

    1. 登录退出功能分析

    1. 流程图

       

    2. 功能

      1. 登录页面

      2. 登录功能

      3. 退出功能

    二、登录页面

    1. 接口设计

    1. 接口说明

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

      登录页面

    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')
    2. 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">
          <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. 业务流程

    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)
    2. 表单 在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文件

    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'),
    ]

    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>
  • 相关阅读:
    最近的题越来越难了,卧槽,搞一上午一题不会,题解也看不懂
    hdu 4630 树状数组 ****
    hdu 3473 划分树 ***
    hdu 3360 最小点覆盖 **
    hdu 1507 记录路径的二分匹配 **
    poj 3177 边双联通 **
    hdu 4612 边双联通 ***
    Elasticsearch聚合后分页深入详解
    redis 五种数据类型及其使用场景
    再有人问你分布式锁,这篇文章扔给他
  • 原文地址:https://www.cnblogs.com/Tmclri/p/11536944.html
Copyright © 2011-2022 走看看