【Python百日进阶-WEB开发】Day180 - Django案例:12用户登录

news2024/11/24 1:38:17

文章目录

  • 十、异步发送短信验证码 - 异步方案Celery
    • 10.1 生产者消费者设计模式
    • 10.2 Celery介绍
    • 10.3 Celery介绍和使用
      • 10.3.1
  • 十一、用户账号 登录
    • 11.1 用户登录
      • 11.1.1 用户登录逻辑分析
      • 11.1.2 用户登录接口设计和定义
      • 11.1.3 用户登录后端逻辑
    • 11.2 多账号登录
      • 11.2.1 自定义用户认证的后端,实现多账号登录
      • 11.2.2 开发环境配置文件dev.py
      • 11.2.3 前端login.html文件
      • 11.2.4 前端login.js文件
    • 11.3 首页用户名显示
      • 11.2.1 方案一:利用jinja2模板提供的变量和方法
      • 11.2.2 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息
    • 11.4 退出登录
      • 11.4.1 Django用户认证系统logout()方法介绍
      • 11.4.2 退出登录后端views.py
      • 11.4.3 定义路由
      • 11.4.4 前端index.html
    • 11.5 判断用户是否登录(LoginRequiredMixin)
      • 11.5.1 用户中心登录
      • 11.5.2 开发配置文件定义LOGIN_URL
      • 11.5.3 修改登录成功重定向指向
  • 十二、QQ登录
    • 12.1 QQ登录开发文档

十、异步发送短信验证码 - 异步方案Celery

在这里插入图片描述
在这里插入图片描述

10.1 生产者消费者设计模式

在这里插入图片描述
在这里插入图片描述

10.2 Celery介绍

在这里插入图片描述
在这里插入图片描述
Celery官方文档:https://docs.celeryproject.org/en/latest/index.html
Celery中文文档:http://docs.jinkan.org/docs/celery/

10.3 Celery介绍和使用

10.3.1

  1. 在项目根目录定义Celery包 celery_tasks

  2. 创建Celery实例

在这里插入图片描述
(meiduo_mall) PS E:\meiduo_project\meiduo_mall> celery -A celery_tasks.main worker -l info
在这里插入图片描述

十一、用户账号 登录

11.1 用户登录

11.1.1 用户登录逻辑分析

在这里插入图片描述

11.1.2 用户登录接口设计和定义

在这里插入图片描述

11.1.3 用户登录后端逻辑

class LoginView(View):
    """ 用户登录 """
    def get(self, request):
        """ 提供用户登录页面 """
        return render(request, 'login.html')

    def post(self, request):
        """  实现用户登录逻辑 """
        # 接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        rememebered = request.POST.get('rememebered')

        # 校验参数
        if not all([username, password]):
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^[a-zA-Z0-9-_]{5,20}$', username):
            return http.HttpResponseForbidden('请输入正确的用户名或手机号!')
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.HttpResponseForbidden('密码8-20位!')

        # 主体逻辑:认证用户(使用账号查询是否存在,账号存在再校验密码)、状态保持
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '账号或密码错误!'})
        
        # 状态保持
        login(request, user)    
        # 使用remembered确定状态保持周期
        if rememebered != 'on':
            # 没有记住登录,状态保持在浏览器会话结束后销毁
            request.session.set_expiry(0)
        else:
            # 记住登录,状态保持周期默认为两周(不要太长,以防攻击者,3600秒即可)
            request.session.set_expiry(None)
            # request.session.set_expiry(3600)
        
        # 为了实现首页展示用户名,需要将用户名缓存到cookie
        response = redirect(reverse('contents:index'))
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
        # 响应结果
        return response

11.2 多账号登录

11.2.1 自定义用户认证的后端,实现多账号登录

users.utils.py文件

# 自定义用户认证的后端,实现多账号登录
from django.contrib.auth.backends import ModelBackend
import re

from meiduo_mall.apps.users.models import User


def get_user_by_account(account):
    """ 通过账户(用户名或密码)获取用户 """
    try:
        if re.match(r'^1[3-9]\d{9}$', account):
            # 匹配成功,account == 手机号
            user = User.objects.get(mobile=account)
        else:
            # 匹配不成功,account == 用户名
            user = User.objects.get(username=account)
    except User.DoesNotExist:
        return None
    else:
        return user


class UsernameMobileBackend(ModelBackend):
    """ 自定义用户认证后端 """
    def authenticate(self, request, username=None, password=None, **kwargs):
        """
        重写用户认证方法
        :param username:用户名或手机号
        :param password:密码明文
        :param kwargs:额外参数
        :return :user
        """
        # 查询用户
        user = get_user_by_account(username)
        # 如果可以查询到用户,还需要校验密码
        if user and user.check_password(password):
            # 返回user
            return user
        else:
            return None

11.2.2 开发环境配置文件dev.py

# 指定自定义用户后端
AUTHENTICATION_BACKENDS = ['users.utils.UsernameMobileBackend']

11.2.3 前端login.html文件

<div class="login_form_bg" id="app">
......
<form action="" method="post" class="login_form" @submit="on_submit" v-cloak>
    {{ csrf_input }}
    <input type="text" v-model="username" @blur="check_username" name="username">
    <div v-show="error_username" class="user_error">请输入正确的用户名或手机号</div>
    <input type="password" v-model="password" @blur="check_password" name="password">
    <div v-show="error_password" class="pwd_error">密码8-20位</div>
    {% if account_errmsg %}
        <div class="pwd_error">{{ account_errmsg }}</div>
    {% endif %}
    <div class="more_input clearfix">
        <input type="checkbox" v-model="remembered" name="remembered">
        <label for="">记住登录</label>
    </div>
    <input type="submit" value="登 录" class="input_submit">
</form>

11.2.4 前端login.js文件

let vm = new Vue({
    el: '#app',
    // 修改Vue变量的读取语法
    delimiters: ['[[', ']]'],
    data: {
        username: '',
        password: '',

        error_username: false,
        error_password: false,
        remembered: false,
    },
    methods: {
        // 检查账号
        check_username(username){
            let re = /^[a-zA-Z0-9-_]{5,20}$/;
            if (re.test(this.username)) {
                this.error_username = false;
            } else {
                this.error_username = true;
            }
        },
        // 检查密码
        check_password(){
            let re = /^[0-9a-zA-Z]{8,20}$/;
            if (re.test(this.password)) {
                this.error_password = false;
            } else {
                this.error_password = true;
            }
        },
        //表单提交
        on_submit(){
            this.check_username();
            this.check_password();
            if (this.error_username == true || this.error_password == true) {
                // 不满足登录条件
                window.event.returnValue = false
            }
        },
        // qq 登录
        qq_login(){
            let next = get_query_string('next') || '/';
            let url = '/qq/login/?next=' + next;
            axios.get(url, {
                responseType: 'json'
            })
                .then(response => {
                    location.href = response.data.login_url;
                })
                .catch(error => {
                    console.log(error.response);
                })
        },
    },
})

11.3 首页用户名显示

11.2.1 方案一:利用jinja2模板提供的变量和方法

最简单,只需要在index.html中调用jinja2模板的user变量的user.is_authenticated方法和user.username属性即可,但首页非静态页面

<!-- 方案一 :使用jinja2模板引擎自带的变量和方法,缺点:需要动态刷新页面,不符合首页静态页面的思想
 使用jinjia2模板引擎自带user变量的自带方法判断 使用jinjia2模板引擎自带user变量渲染
{% if user.is_authenticated %}  
    <div class="login_btn fl">
        欢迎您:<em>{{ user.username }}</em> 
        <span>|</span>
        <a href="javascript:;" class="quit">退出</a>
    </div>
{% else %}
    <div class="login_btn fl">
        <a href="login/">登录</a>
        <span>|</span>
        <a href="register/">注册</a>
    </div>
{% endif %} -->

11.2.2 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息

index.html文件

<!-- 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息 -->
<div v-if="username" class="login_btn fl">
    欢迎您:<em>[[ username ]]</em>
    <span>|</span>
    <a href="javascript:;" class="quit">退出</a>
</div>
<div v-else class="login_btn fl">
    <a href="login/">登录</a>
    <span>|</span>
    <a href="register/">注册</a>
</div>

index.js文件

let vm = new Vue({
    el: '#app',
    delimiters:['[[', ']]'],
    data:{
        username: getCookie('username'),
        f1_tab: 1, //1F标签页控制
        f2_tab: 1, //2F标签页控制
        f3_tab: 1, //3F标签页控制

        // 渲染首页购物车数据
        cart_total_count: 0,
        carts: [],
    },

common.js文件

//获取cookie
function getCookie(name) {
    let r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
    return r ? r[1] : undefined;
}

users.views.py后端用户登录和用户注册的最好,响应结果使用以下代码

# 为了实现首页展示用户名,需要将用户名缓存到cookie
response = redirect(reverse('contents:index'))
response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
# 响应结果
return response

11.4 退出登录

11.4.1 Django用户认证系统logout()方法介绍

原理:清理session和cookie

11.4.2 退出登录后端views.py

from django.contrib.auth import login, authenticate, logout
class LogoutView(View):
    """ 用户退出登录 """
    def get(self, request):
        """ 实现用户退出登录的逻辑 """
        # 清除状态保持信息
        logout(request)
        # 删除cookie中的用户名
        response = redirect(reverse('contents:index'))
        response.delete_cookie('username')

        # 响应结果,重定向到首页
        return response

11.4.3 定义路由

 # 退出登录
 path('logout/', views.LogoutView.as_view(), name='logout')

11.4.4 前端index.html

 <!-- 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息 -->
 <div v-if="username" class="login_btn fl">
     欢迎您:<em>[[ username ]]</em>
     <span>|</span>
     <!-- 使用jinja2模板的反向解析 -->
     <a href="{{ url('users:logout') }}" class="quit">退出</a>
 </div>

11.5 判断用户是否登录(LoginRequiredMixin)

应用场景:用户中心、订单系统,
Django用户认证系统提供了方法 request.user.is_authenticated() 来判断用户是否登录。如果通过登录验证则返回True,否则false。
LoginRequiredMixin封装了判断用户是否登录的操作。

11.5.1 用户中心登录

users.views.py

from django.contrib.auth.mixins import LoginRequiredMixin

class UserInfoView(LoginRequiredMixin, View):
    """ 用户中心 """
    def get(self, request):
        """ 提供用户中心的页面 """
        # if request.user.is_authenticated:     # 判断用户是否登录的过程
        #     return  render(request, 'user_center_info.html')
        # else:
        #     return redirect(reverse('users:login'))
        # login_url = reverse('/login/')    # dev.py配置文件中已经指定 LOGIN_URL = '/login/'
        # redirect_field_name = 'user_center_info.html'     # LoginRequiredMixin有默认值next
        return render(request, 'user_center_info.html')

11.5.2 开发配置文件定义LOGIN_URL

# 判断用户是否登录后,指定未登录用户重定向的地址
LOGIN_URL = '/login/'

11.5.3 修改登录成功重定向指向

users.views.py

# 根据发起登录请求的模块,登录成功重定向到不同的页面
next = request.GET.get('next')
if next:    # LoginRequiredMixin的内置变量,存储登录要求来自哪里
    response = redirect(next)   # next存在,重定向到登录前模块页面
else:
    response = redirect(reverse('contents:index'))  # next不存在,重定向到首页
# 为了实现首页展示用户名,需要将用户名缓存到cookie
response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
# 响应结果,根据请求来源重定向
return response

十二、QQ登录

12.1 QQ登录开发文档

  1. QQ互联开发者申请步骤
    相关链接:https://wiki.connect.qq.com/成为开发者
    在这里插入图片描述

在QQ互联开放平台首页 https://connect.qq.com/ ,点击右上角的“登录”按钮,使用QQ帐号登录
在这里插入图片描述

公司认证,填写公司信息在这里插入图片描述
在这里插入图片描述
2. QQ互联应用申请步骤
以下为演示图片,需要提前申请域名提供备案号,都必须是真实信息。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
APP ID:101518219
APP KEY:418d84ebdc7241efb79536886ae95224
网站地址:www.meiduo.site
网站回调地址:http://www.meiduo.site:8000/oauth_callback
3. 网站对接QQ登录步骤
https://wiki.connect.qq.com/准备工作_oauth2-0
在这里插入图片描述
https://wiki.connect.qq.com/放置qq登录按钮_oauth2-0
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/14353.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实战三:基于LGB实现车联网大数据碰撞识别 代码+数据(非常详细可作为毕设)

项目介绍&#xff1a; 使用的数据为采集车辆信号。车辆信息非常多&#xff0c;而且用户路况信息和使用偏好千人千面&#xff0c;很难找到一种准确识别碰撞的方法&#xff0c;希望参赛者通过车联网大数据识别车辆碰撞和碰撞时间。车辆标签信息如下&#xff1a; 车号LabelCollec…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.5 SpringBoot 整合 Redis

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.5 SpringBoot 整合 Redis4.5.1 环境准备4.5.2 使用…

多系统-单点登录测试

单点登录 文章目录单点登录单点登录 单点登录全程Single Sign On&#xff08;SSO&#xff09;,在多个应用系统中&#xff0c;用户只需要登录一次就可以访问所有相互信任的应用系统&#xff0c;包括单点登录和单点注销两部分&#xff0c;是目前比较流行的企业业务整合的解决方案…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.1 内置数据源

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.1 内置数据源4.1.1 现有数据层解决方案4.1.2 小结…

波束形成,通过matlab仿真不同参数的波束形成以及旁絆级

目录 1.算法概述 2.仿真效果预览 3.核心MATLAB代码预览 4.完整MATLAB程序 1.算法概述 波束成形技术&#xff08;Beam Forming&#xff0c;BF&#xff09;可分为自适应波束成形、固定波束和切换波束成形技术。固定波束即天线的方向图是固定的&#xff0c;把IS-95中的三个120…

同花顺_代码解析_技术指标_B

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 BBI BBIBOLL BETA BIAS BIASFS BOLL BOLLFS BTI BBI 多空指标 多空指标:(收盘价的M1日简单移动平均收盘价的M2日简单移动平均收盘价的M3日简单移动平均收盘价的M4日简单移动平均…

G蛋白偶联受体/激酶/离子通道——高通量筛选

GPCR Library &#xff08;含54,080 种化合物&#xff09;用于发现新的GPCR配体 G蛋白偶联受体 (GPCR)是新药研发人员关注的一类重要蛋白&#xff0c;三分之一FDA 批准药物靶向 GPCR。GPCR Library 涵盖了广泛的 GPCR 靶标&#xff0c;库中化合物具有新颖性和高度多样性的特…

C++不知算法系列之集结常规算法思想

1. 前言 数据结构和算法是程序的 2 大基础结构&#xff0c;如果说数据是程序的汽油&#xff0c;算法则就是程序的发动机。 什么是数据结构&#xff1f; 指数据之间的逻辑关系以及在计算机中的存储方式&#xff0c;数据的存储方式会影响到获取数据的便利性。 现实生活中&…

JVM和Java体系结构

前言 作为Java工程师的你曾被伤害过吗&#xff1f;你是否也遇到过这些问题&#xff1f; 运行着的线上系统突然卡死&#xff0c;系统无法访问&#xff0c;甚至直接OOMM&#xff01; 想解决线上JVM GC问题&#xff0c;但却无从下手。 新项目上线&#xff0c;对各种JVM参数设置…

【LeetCode】【简单】【4】70. 爬楼梯

题目 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 动态规划 参考链接&#xff1a;动态规划详解 简单来说&#xff0c;动态规划其实就是&#xff0c;给定一个问题&#xff0c;我们把它拆成一个…

贯叶连翘及其天然产物的介绍

贯叶连翘 (Hyperlcurn perforatum L.) 为藤黄科 (Guttiferae) 植物&#xff0c;又名贯叶金丝桃&#xff0c;赶山鞭&#xff0c;小对叶草、千层楼等。迄今为止&#xff0c;已有众多的活性化合物从贯叶连翘中被分离出来。贯叶连翘中不同的成分具有多重药理活性&#xff0c;如其中…

数据结构题目收录(十八)

1、若某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素&#xff0c;则采用____存储方式最节省运算时间。 A&#xff1a;单链表B&#xff1a;仅有头指针的单循环链表C&#xff1a;双链表D&#xff1a;仅有尾指针的单循环链表 解析 选项A、单链表插入…

Java_Map

字典(Map) 概述 HashMap 定义方法 public static void main(String[] args) {// HashMap<Integer, String> Map new HashMap<Integer, String>(); // 定义方法一Map<Integer, String> map new HashMap<Integer, String>(); // 定义方法二// map没…

(续)SSM整合之springmvc笔记(域对象共享数据)(P136-138)

目录 一 使用ServletAPI向request域对象共享数据 二 使用ModelAndView向request域对象共享数据 1 新建TestScopeController 2 index.html 3 书写TestScopeController 4 success.html 5 测试 三 使用Model向request域对象共享数据 1 index.html 2 TestSc…

HTNL---表格标签和列表标签

一、表格标签 对于表格我想就不用做很多细说了吧&#xff0c;Excel大家应该都知道。HTML中的表格不是用来布局页面的而是用来展示数据的。 1&#xff1a;表格标签基本使用 <table> <tr><th>姓名</th> <th>年龄</th> <td>第一</…

【Note5】macvlan,spi,rsyslog,sol

文章目录1.BMC虚拟多网口&#xff1a;macvlan是kernel提供的一种网卡虚拟化技术&#xff0c;可将网卡&#xff08;不一定是真实的物理网卡&#xff09;虚拟出多个接口&#xff0c;这网卡称为master或父接口&#xff0c;这些虚拟接口和外面环境通信都是通过父接口1.1 bridge&…

RESTful 接口设计拓展,接口设计注意事项,注解的简化

文章目录RESTful 接口设计拓展1.多参数传递2.URL拓展3.RESTful接口注意事项4.注解的简化RESTful 接口设计拓展 1.多参数传递 /*** 获取某一个员工&#xff0c;多参数* 1. 请求路径--确认资源--员工--/employees* 2. 请求方法--get* 3. 请求参数--id&#xff0c;name,age* 4. …

Python接口测试之requests详介与实战

目录 requests介绍 1、简述发展史 2、安装 3、官方自评 4、requests支持的请求类型 4、requests的参数与返回 requests接口请求Python脚本实战 1、GET接口实战 2、POST接口实战 3、PUT接口实战 4、DELETE接口实战 requests介绍 Http网络接口请求库 1、简述发展史 …

设计师找灵感就上这几个网站。

推荐5个设计师必备的设计灵感网站&#xff0c;希望对你有帮助&#xff01; 1、pinterest&#xff08;梯子&#xff09; https://www.pinterest.es/Pinterest是以瀑布流的方式来展示图片&#xff0c;在算法上也会根据你的浏览和识别的图片去做推算。 所以Pinterest是需要“经营”…

网络编程概述

Java是 Internet 上的语言&#xff0c;它从语言级上提供了对网络应用程 序的支持&#xff0c;程序员能够很容易开发常见的网络应用程序。 Java提供的网络类库&#xff0c;可以实现无痛的网络连接&#xff0c;联网的底层 细节被隐藏在 Java 的本机安装系统里&#xff0c;由 JVM …