【Django开发】0到1美多商城项目md教程第4篇:图形验证码,1. 图形验证码接口设计【附代码文档】

美多商城完整教程(附代码资料)主要内容讲述:欢迎来到美多商城!,项目准备。展示用户注册页面,创建用户模块子应用。用户注册业务实现,用户注册前端逻辑。图形验证码,图形验证码接口设计和定义。短信验证码,避免频繁发送短信验证码。账号登录,用户名登录。登录,登录开发文档。用户基本信息,查询并渲染用户基本信息。收货地址,省市区三级联动。收货地址,展示地址前后端逻辑。商品数据库表设计,SPU和SKU。准备商品数据,容器化方案Docker。首页广告,展示首页商品频道分类。商品列表页,列表页面包屑导航。商品搜索,Haystack扩展建立索引。商品详情页,统计分类商品访问量。购物车管理,添加购物车。购物车管理,删除购物车。订单,结算订单。提交订单,使用乐观锁并发下单。对接系统,订单支付功能。页面静态化,首页广告页面静态化。MySQL读写分离,MySQL主从同步。

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~


全套教程部分目录:


部分文件图片:

图形验证码

图形验证码接口设计和定义

1. 图形验证码接口设计

1.请求方式

选项方案
请求方法GET
请求地址image_codes/(?P[\w-]+)/
>
2.请求参数:路径参数
参数名类型是否必传说明
uuidstring唯一编号
>
3.响应结果:image/jpg

2. 图形验证码接口定义

1.图形验证码视图

class ImageCodeView(View):
    """图形验证码"""

    def get(self, request, uuid):
        """
        :param request: 请求对象
        :param uuid: 唯一标识图形验证码所属于的用户
        :return: image/jpg
        """
        pass

2.总路由

# verifications


url(r'^', include('verifications.urls')),

3.子路由

# 图形验证码


url(r'^image_codes/(?P<uuid>[\w-]+)/$', views.ImageCodeView.as_view()),

图形验证码后端逻辑

1. 准备captcha扩展包

提示:captcha扩展包用于后端生成图形验证码

可能出现的错误

  • 报错原因:环境中没有Python处理图片的库:PIL

解决办法

  • 安装Python处理图片的库:pip install Pillow

2. 准备Redis数据库

准备Redis的2号库存储验证码数据

"verify_code": { # 验证码
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },

3. 图形验证码后端逻辑实现

class ImageCodeView(View):
    """图形验证码"""

    def get(self, request, uuid):
        """
        :param request: 请求对象
        :param uuid: 唯一标识图形验证码所属于的用户
        :return: image/jpg
        """
        # 生成图片验证码
        text, image = captcha.generate_captcha()

        # 保存图片验证码
        redis_conn = get_redis_connection('verify_code')
        redis_conn.setex('img_%s' % uuid, constants.IMAGE_CODE_REDIS_EXPIRES, text)

        # 响应图片验证码
        return http.HttpResponse(image, content_type='image/jpg')

图形验证码前端逻辑

1. Vue实现图形验证码展示

1.register.js

mounted(){
    // 生成图形验证码
    this.generate_image_code();
},
methods: {
    // 生成图形验证码
    generate_image_code(){
        // 生成UUID。generateUUID() : 封装在common.js文件中,需要提前引入
        this.uuid = generateUUID();
        // 拼接图形验证码请求地址
        this.image_code_url = "/image_codes/" + this.uuid + "/";
    },
    ......
}

2.register.html

<li>
    <label>图形验证码:</label>
    <input type="text" name="image_code" id="pic_code" class="msg_input">
    <img :src="image_code_url" @click="generate_image_code" alt="图形验证码" class="pic_code">
    <span class="error_tip">请填写图形验证码</span>
</li>

3.图形验证码展示和存储效果

2. Vue实现图形验证码校验

1.register.html

<li>
    <label>图形验证码:</label>
    <input type="text" v-model="image_code" @blur="check_image_code" name="image_code" id="pic_code" class="msg_input">
    <img :src="image_code_url" @click="generate_image_code" alt="图形验证码" class="pic_code">
    <span class="error_tip" v-show="error_image_code">[[ error_image_code_message ]]</span>
</li>

2.register.js

check_image_code(){
    if(!this.image_code) {
        this.error_image_code_message = '请填写图片验证码';
        this.error_image_code = true;
    } else {
        this.error_image_code = false;
    }
},

3.图形验证码校验效果

短信验证码

短信验证码逻辑分析

知识要点

  1. 保存短信验证码是为注册做准备的。
  2. 为了避免用户使用图形验证码恶意测试,后端提取了图形验证码后,立即删除图形验证码。
  3. Django不具备发送短信的功能,所以我们借助第三方的容联云通讯短信平台来帮助我们发送短信验证码。

容联云通讯短信平台

1. 容联云通讯短信平台介绍

1.容联云官网

  • 容联云通讯网址:[
  • 注册并登陆

2.容联云管理控制台

3.容联云创建应用

4.应用申请上线,并进行资质认证

5.完成资质认证,应用成功上线

6.添加测试号码

7.短信模板

2. 容联云通讯短信SDK测试

1.模板短信SDK下载

  • [

    2.模板短信SDK使用说明

  • [

    3.集成模板短信SDK

  • CCPRestSDK.py:由容联云通讯开发者编写的官方SDK文件,包括发送模板短信的方法

  • ccp_sms.py:调用发送模板短信的方法

4.模板短信SDK测试

  • ccp_sms.py文件中
# -*- coding:utf-8 -*-



from verifications.libs.yuntongxun.CCPRestSDK import REST



# 说明:主账号,登陆云通讯网站后,可在"控制台-应用"中看到开发者主账号ACCOUNT SID


_accountSid = '8aaf070862181ad5016236f3bcc811d5'



# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN


_accountToken = '4e831592bd464663b0de944df13f16ef'



# 请使用管理控制台首页的APPID或自己创建应用的APPID


_appId = '8aaf070868747811016883f12ef3062c'



# 说明:请求地址,生产环境配置成app.cloopen.com


_serverIP = 'sandboxapp.cloopen.com'



# 说明:请求端口 ,生产环境为8883


_serverPort = "8883"



# 说明:REST API版本号保持不变


_softVersion = '2013-12-26'



# 云通讯官方提供的发送短信代码实例




# 发送模板短信




# @param to 手机号码




# @param datas 内容数据 格式为数组 例如:{'12','34'},如不需替换请填 ''




# @param $tempId 模板Id


def sendTemplateSMS(to, datas, tempId):
    # 初始化REST SDK
    rest = REST(_serverIP, _serverPort, _softVersion)
    rest.setAccount(_accountSid, _accountToken)
    rest.setAppId(_appId)

    result = rest.sendTemplateSMS(to, datas, tempId)
    print(result)
    for k, v in result.items():

        if k == 'templateSMS':
            for k, s in v.items():
                print('%s:%s' % (k, s))
        else:
            print('%s:%s' % (k, v))

if __name__ == '__main__':
    # 注意: 测试的短信模板编号为1
    sendTemplateSMS('17600992168', ['123456', 5], 1)

5.模板短信SDK返回结果说明

{
    'statusCode': '000000', // 状态码。'000000'表示成功,反之,失败
    'templateSMS': 
        {
            'smsMessageSid': 'b5768b09e5bc4a369ed35c444c13a1eb', // 短信唯一标识符
            'dateCreated': '20190125185207' // 短信发送时间
        }
}

3. 封装发送短信单例类

1.封装发送短信单例类

class CCP(object):
    """发送短信的单例类"""

    def __new__(cls, *args, **kwargs):
        # 判断是否存在类属性_instance,_instance是类CCP的唯一对象,即单例
        if not hasattr(CCP, "_instance"):
            cls._instance = super(CCP, cls).__new__(cls, *args, **kwargs)
            cls._instance.rest = REST(_serverIP, _serverPort, _softVersion)
            cls._instance.rest.setAccount(_accountSid, _accountToken)
            cls._instance.rest.setAppId(_appId)
        return cls._instance

2.封装发送短信单例方法

def send_template_sms(self, to, datas, temp_id):
    """
    发送模板短信单例方法
    :param to: 注册手机号
    :param datas: 模板短信内容数据,格式为列表,例如:['123456', 5],如不需替换请填 ''
    :param temp_id: 模板编号,默认免费提供id为1的模板
    :return: 发短信结果
    """
    result = self.rest.sendTemplateSMS(to, datas, temp_id)
    if result.get("statusCode") == "000000":
        # 返回0,表示发送短信成功
        return 0
    else:
        # 返回-1,表示发送失败
        return -1

3.测试单例类发送模板短信结果

if __name__ == '__main__':
    # 注意: 测试的短信模板编号为1
    CCP().send_template_sms('17600992168', ['123456', 5], 1)

4. 知识要点

  1. 容联云通讯只是发送短信的平台之一,还有其他云平台可用,比如,阿里云等,实现套路都是相通的。
  2. 将发短信的类封装为单例,属于性能优化的一种方案。

短信验证码后端逻辑

1. 短信验证码接口设计

1.请求方式

选项方案
请求方法GET
请求地址/sms_codes/(?P1[3-9]\d{9})/
>
2.请求参数:路径参数和查询字符串
参数名类型是否必传说明
mobilestring手机号
image_codestring图形验证码
uuidstring唯一编号
>
3.响应结果:JSON
字段说明
code状态码
errmsg错误信息

2. 短信验证码接口定义

class SMSCodeView(View):
    """短信验证码"""

    def get(self, reqeust, mobile):
        """
        :param reqeust: 请求对象
        :param mobile: 手机号
        :return: JSON
        """
        pass

3. 短信验证码后端逻辑实现

class SMSCodeView(View):
    """短信验证码"""

    def get(self, reqeust, mobile):
        """
        :param reqeust: 请求对象
        :param mobile: 手机号
        :return: JSON
        """
        # 接收参数
        image_code_client = reqeust.GET.get('image_code')
        uuid = reqeust.GET.get('uuid')

        # 校验参数
        if not all([image_code_client, uuid]):
            return http.JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '缺少必传参数'})

        # 创建连接到redis的对象
        redis_conn = get_redis_connection('verify_code')
        # 提取图形验证码
        image_code_server = redis_conn.get('img_%s' % uuid)
        if image_code_server is None:
            # 图形验证码过期或者不存在
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码失效'})
        # 删除图形验证码,避免恶意测试图形验证码
        try:
            redis_conn.delete('img_%s' % uuid)
        except Exception as e:
            logger.error(e)
        # 对比图形验证码
        image_code_server = image_code_server.decode()  # bytes转字符串
        if image_code_client.lower() != image_code_server.lower():  # 转小写后比较
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '输入图形验证码有误'})

        # 生成短信验证码:生成6位数验证码
        sms_code = '%06d' % random.randint(0, 999999)
        logger.info(sms_code)
        # 保存短信验证码
        redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # 发送短信验证码
        CCP().send_template_sms(mobile,[sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID)

        # 响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信成功'})

短信验证码前端逻辑

1. Vue绑定短信验证码界面

1.register.html

<li>
    <label>短信验证码:</label>
    <input type="text" v-model="sms_code" @blur="check_sms_code" name="sms_code" id="msg_code" class="msg_input">
    <a @click="send_sms_code" class="get_msg_code">[[ sms_code_tip ]]</a>
    <span class="error_tip" v-show="error_sms_code">[[ error_sms_code_message ]]</span>
</li>

2.register.js

check_sms_code(){
    if(this.sms_code.length != 6){
        this.error_sms_code_message = '请填写短信验证码';
        this.error_sms_code = true;
    } else {
        this.error_sms_code = false;
    }
},

2. axios请求短信验证码

1.发送短信验证码事件处理

send_sms_code(){
    // 避免重复点击
    if (this.sending_flag == true) {
        return;
    }
    this.sending_flag = true;

    // 校验参数
    this.check_mobile();
    this.check_image_code();
    if (this.error_mobile == true || this.error_image_code == true) {
        this.sending_flag = false;
        return;
    }

    // 请求短信验证码
    let url = '/sms_codes/' + this.mobile + '/?image_code=' + this.image_code+'&uuid='+ this.uuid;
    axios.get(url, {
        responseType: 'json'
    })
        .then(response => {
            if (response.data.code == '0') {
                // 倒计时60秒
                var num = 60;
                var t = setInterval(() => {
                    if (num == 1) {
                        clearInterval(t);
                        this.sms_code_tip = '获取短信验证码';
                        this.sending_flag = false;
                    } else {
                        num -= 1;
                        // 展示倒计时信息
                        this.sms_code_tip = num + '秒';
                    }
                }, 1000, 60)
            } else {
                if (response.data.code == '4001') {
                    this.error_image_code_message = response.data.errmsg;
                    this.error_image_code = true;
                } else { // 4002
                    this.error_sms_code_message = response.data.errmsg;
                    this.error_sms_code = true;
                }
                this.generate_image_code();
                this.sending_flag = false;
            }
        })
        .catch(error => {
            console.log(error.response);
            this.sending_flag = false;
        })
},

2.发送短信验证码效果展示

补充注册时短信验证逻辑

1. 补充注册时短信验证后端逻辑

1.接收短信验证码参数

sms_code_client = request.POST.get('sms_code')

2.保存注册数据之前,对比短信验证码

redis_conn = get_redis_connection('verify_code')
sms_code_server = redis_conn.get('sms_%s' % mobile)
if sms_code_server is None:
    return render(request, 'register.html', {'sms_code_errmsg':'无效的短信验证码'})
if sms_code_client != sms_code_server.decode():
    return render(request, 'register.html', {'sms_code_errmsg': '输入短信验证码有误'})

2. 补充注册时短信验证前端逻辑

1.register.html

<li>
    <label>短信验证码:</label>
    <input type="text" v-model="sms_code" @blur="check_sms_code" name="sms_code" id="msg_code" class="msg_input">
    <a @click="send_sms_code" class="get_msg_code">[[ sms_code_tip ]]</a>
    <span v-show="error_sms_code" class="error_tip">[[ error_sms_code_message ]]</span>
    {% if sms_code_errmsg %}
        <span class="error_tip">{{ sms_code_errmsg }} </span>
    {% endif %}
</li>

未完待续, 同学们请等待下一期

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL,group by分组后分别计算组内不同值的数量

SQL&#xff0c;group by分组后分别计算组内不同值的数量 如现有一张购物表shopping 先要求小明和小红分别买了多少笔和多少橡皮&#xff0c;形成以下格式 SELECT name,COUNT(*) FROM shopping GROUP BY name;SELECT name AS 姓名,SUM( CASE WHEN cargo 笔 THEN 1 ELSE 0 END)…

关于Oracle VM VirtualBox无法查询IP地址的原因

1.如下&#xff0c;输入ifconfig却没有显示我框住的显示IP。 2.原因有可能&#xff1a; &#xff08;1&#xff09;主机没连上网络。 &#xff08;2&#xff09;虚拟机网络设置不正确。

Python问题列表

文章目录 1、使用pip安装的模块都存放到哪里了&#xff1f;2、安装fitz包报错&#xff0c;如何解决&#xff1f;3、python代码运行时&#xff0c;控制台输出乱码如何解决。4、vscode中第三方库不自动补齐 1、使用pip安装的模块都存放到哪里了&#xff1f; 答&#xff1a; pip是…

GLTFExporter是一个用于将3D场景导出为glTF格式的JavaScript库。

demo案例 GLTFExporter是一个用于将3D场景导出为glTF格式的JavaScript库。下面我将逐个讲解其入参、出参、属性、方法以及API使用方式。 入参&#xff08;Input Parameters&#xff09;: GLTFExporter的主要入参是要导出的场景对象和一些导出选项。具体来说&#xff1a; s…

Linux 入门及其基本指令(一文即入门)

目录 0 .引言 1. XShell 远程登录 Linux 1.1 云服务器 1.2. XShell 远程登陆 Linux 2. 详解 Linux 基本指令 2.1 ls 指令 2.2 pwd 指令 2.3 cd 指令 2.4 touch 指令 2.5 mkdir指令 2.6 rmdir指令 && rm 指令 0 .引言 如今&#xff0c;Linux 在服务器…

【Qt】系统相关(事件)

目录 一、概念二、事件处理三、鼠标事件1.鼠标点击事件2.鼠标释放事件3.鼠标移动事件 四、按键事件 一、概念 事件是应用程序内部或者外部产生的事情或者动作的统称。在Qt中使用一个对象来表示一个事件。所有的Qt事件均继承于抽象类QEvent。事件是由系统或者Qt平台本身在不同的…

【数据结构】——树和二叉树相关概念(全网超级详解)

创作不易&#xff0c;家人们来一波三连吧&#xff1f;&#xff01; 前言 世界上最大的树--雪曼将军树&#xff0c;这棵参天大树不是最长也不是最宽&#xff0c;是不是很奇怪&#xff0c;大只是他的体积是最大的&#xff0c;看图片肯定是感触不深&#xff0c;大家可以自己去看…

电脑卡顿怎么办?教你三招,轻松解决卡顿问题!

在现代社会&#xff0c;电脑已成为我们日常生活和工作中不可或缺的工具。然而&#xff0c;随着使用时间的增长&#xff0c;不少用户可能会遇到电脑卡顿的问题。卡顿不仅影响工作效率&#xff0c;还可能造成数据丢失等严重后果。本文将为大家介绍三种解决电脑卡顿问题的方法&…

使用 CSS 创建响应式图像滑块

使用 CSS 创建响应式图像滑块 效果展示 PC 端效果 移动端 / iPad 效果 CSS 知识点 媒体查询知识点复习position: absolute 的使用复习:nth-child 的使用复习 页面需求及实现思路 需求 页面会根据设备大小形成不同的布局方式当前展示图片放大并且展示对应的标题和描述其他…

智能公交调度管理服务系统

一、 背景 从上世纪末开始&#xff0c;为了缓解经济发展带来的道路交通方面的压力&#xff0c;绝大多数国家的公共交通部门方面进行了大量的投入&#xff0c;都在研发各种先进的技术来改善交通状况&#xff0c;其中包括了对公交 车的定位、对车辆实施全方位的虽然有的监控、自…

Leo赠书活动-23期 【Python数据分析】文末送书

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

告别繁琐代码,只需简单拖拽,便可从0到1开发!

告别繁琐代码&#xff0c;拥抱科技未来&#xff01;只需简单拖拽&#xff0c;便可从0到1开发&#xff01;代码即刻生成&#xff0c;一键下载&#xff0c;轻松上手。我们的低代码平台&#xff0c;不仅高效便捷&#xff0c;更完全开源&#xff0c;让你自由探索编程的无限可能&…

Vue3性能优化之自定义指令实现图片懒加载

图片懒加载是一种常见性能优化的方式&#xff0c;进入网址时不全部加载图片 当用户进入图片可视区域时加载 不仅大大减少了服务器的压力 也可以时首屏时间变短 图片懒加载的实现原理&#xff1a;在图片没进入可视区域的时候&#xff0c;只需要让 img 标签的 src 属性指向一张…

发票是扫码验真好,还是OCR后进行验真好?

随着科技的进步&#xff0c;电子发票的普及使得发票的验真方式也在不断演进。目前&#xff0c;我们常见的发票验真方式主要有两种&#xff1a;一种是扫描发票上的二维码进行验真&#xff0c;另一种是通过OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别…

Python爬虫实战之爬取微博热搜

前言 在开始之前&#xff0c;我们需要了解一些基本的爬虫知识。Python爬虫是一种自动化获取网页内容的技术&#xff0c;可以模拟浏览器行为&#xff0c;获取网页源代码&#xff0c;并从中提取所需的信息。在爬取微博热搜榜单时&#xff0c;我们需要发送HTTP请求获取网页源代码…

263:vue+openlayers 高德地图坐标转换 WGS84-GCJ02

第263个 点击查看专栏目录 本示例演示如何在vue+openlayers中将 WGS84坐标转化为GCJ02坐标,从而使得高德地图能正确的显示物体的坐标点。 84坐标系可以理解为是真实坐标系,是一个地点的实际坐标值。02坐标系是加密后的坐标系,是为了国家安全考虑。对应的不是实际的坐标值,…

C语言键盘输入与屏幕输出——数据的格式化键盘输入

目录 数据的格式化键盘输入 输入数据的格式控制 scanf&#xff08;&#xff09;的格式字符 scanf()的格式修饰符 数据的格式化键盘输入 格式 scanf&#xff08;格式控制字符串&#xff0c;输入地址表&#xff09;&#xff1b; 输入数据的格式控制 格式 scanf&#xff08;…

500万美元!谷歌设超级大奖推动量子计算实用化

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨王珩 编译/排版丨浪味仙 沛贤 深度好文&#xff1a;1500字丨10分钟阅读 近日&#xff0c;谷歌联合 XPRIZE基金会&#xff0c;发起一项价值 500 万美元、为期 3 年的全球量子应用竞赛&am…

python---基础(一)

文章目录 前言1.对象的基本组成2.变量和常量2.1.变量的声明2.2.常量_链式赋值_系列解包赋值2.2.1.常量是不是真的常量&#xff1f;2.2.2.链式赋值2.2.3.系列解包赋值 3.内置数据类型_基本算数运算符3.1四种内置数据类型3.2.基本运算符3.3.divmod() 前言 这几年&#xff0c;随着…