4.1 django项目-新闻博客系统之用户登录登出

04 用户登录登出

一、用户登录

1、功能分析

登录页面

登录功能

2、用户登录流程

登录注册流程图 (2).png

3、登录页面

1、接口设计

  1. 接口说明

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

    登录页面

2、后端代码

user/views.py代码:

class Login_view(View):
    '''
    用户登录类视图
    '''
    def get(self, request):
        return render(request, 'user/login.html'

路由

path('login/', views.Login_view.as_view(), name='login'),

4、登录功能

1. 业务流程

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

2.接口设计

接口说明:

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

参数说明:

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

返回结果:

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

3.后端代码

class Login_view(View):
    '''
    用户登录类视图
    '''
    def get(self, request):
        return render(request, 'user/login.html')

    def post(self, request):
        form = Checklogin(request.POST)
        if form.is_valid():
            user = form.cleaned_data.get('user')
            remember = form.cleaned_data.get('remember')
            if remember:
                # 设置session过期时间为7天
                request.session.set_expiry(constants.USER_SESSION_EXPIRY)
            else:
                # 设置session关闭浏览器过期
                request.session.set_expiry(0)
            login(request, user)
            return json_response(errmsg='恭喜登录成功!')
        else:
            errmsg = form.get_errors()

            return json_response(errno=Code.PARAMERR, errmsg=errmsg)

forms.py

import re
from django import forms
from django.core.validators import RegexValidator
from django_redis import get_redis_connection
from django.db.models import Q
from .models import User
from verification import constants

# 创建手机号码的正则校验器
phone_validator = RegexValidator(r'^1[3-9]\d{9}$', '手机号码格式不正确')
username_validator = RegexValidator(r'^\D\w{5,19}$', '请输入以非数字开头的用户名,6-20个字符')

class Checklogin(forms.Form):
    account = forms.CharField(error_messages={
                                   'required': '账号不能为空',
                               }
                               )

    password = forms.CharField(max_length=20,
                               min_length=6,
                               error_messages={
                                   'max_length': '密码长度有误',
                                   'min_length': '密码长度有误',
                                   'required': '密码不能为空',
                               }
                               )

    remember = forms.BooleanField(required=False)

    def clean_account(self):
        account = self.cleaned_data.get('account')
        if not (re.match(r'^1[3-9]\d{9}$', account) or re.match(r'^\D\w{5,19}$', account)):
            raise forms.ValidationError('账号格式有误')
        return account

    def clean(self):
        '''
        校验用户名、密码
        :return:
        '''
        cleaned_data = super().clean()
        account = cleaned_data.get('account')
        password = cleaned_data.get('password')

        user_queryset = User.objects.filter(Q(username=account) | Q(phone=account))
        if user_queryset:
            user = user_queryset.first()
            if not user.check_password(password):
                raise forms.ValidationError('账号或密码错误')
            else:
                cleaned_data['user'] = user
        else:
            raise forms.ValidationError('账号不存在')

        return cleaned_data

    def get_errors(self):
        errors = self.errors.get_json_data()
        err_msg_list = []
        for item in errors.values():
            for ite in item:
                err_msg_list.append(ite.get('message'))
        err_msg_str = '/'.join(err_msg_list)
        return err_msg_str

4、前端html

{% 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 %}
    <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>
    </form>
  </div>
</main>
{% endblock main %}

{% block otherjs %}
    <script src="{% static 'js/base/message.js' %}"></script>
    <script src="{% static 'js/user/login.js' %}"></script>
{% endblock otherjs %}

5、前端js

$(function () {

    // 提交表单
    let $suumitBnt = $('.login-btn');
    $suumitBnt.click((event)=>{
        // 阻止表单提交
        event.preventDefault();
        sAccount = $('input[name="account"]').val();
        if(!((/^1[3-9]\d{9}$/).test(sAccount) || (/^\D\w{5,19}$/).test(sAccount)))
        {
            message.showError('请输入正确的手机号码,或者以非数字开头包含6-20个字符的用户名');
            return
        }
        sPassword = $('input[name="password"]').val();
        if(!(/^.{6,20}$/).test(sPassword))
        {
            message.showError('密码长度错误!');
            return
        }
        sRemember = $('input[name="remember"]').is(':checked');
        $
            .ajax({
                url:'/login/',
                type:'POST',
                data:{
                    account:sAccount,
                    password:sPassword,
                    remember:sRemember
                },
                dataType:'json'
            })
            .done((resp)=>{
                if(resp.errno === '0'){
                    message.showSuccess(resp.errmsg);
                    setTimeout(function () {
                        //注册成功之后重定向到打开登录页面之前的页面
                        if(!document.referrer || document.referrer.includes('/login/') || document.referrer.includes('/register/')){
                            window.location.href = '/'
                        }else {
                            window.location.href = document.referrer
                        }
                    }, 3000)
                }
                else
                {
                    message.showError(resp.errmsg);
                }
            })
            .fail(()=>{
                message.showError('服务器超时,请刷新重试!')
            });
    })


});

二、用户登出

1、接口设计

接口说明:

类目 说明
请求方法 GET
url定义 /logou/
参数格式 无参数

2、后端代码

def user_logout(request):
    logout(request)
    return redirect(reverse('user:login'))

路由

path('logout/', views.user_logout, name='logout'),
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容