问: 为什么要把验证码改为异步的?
答: 和异步相对应的是同步 用户输入验证码的时候要先发送验证码;
会有一个等待的过程; 用户要等待验证码的发送,发送之后要输入验证码;
是这样一个流程; 如果有10000个用户一起发送验证码,会导致程序堵塞,
程序就会中断执行;
(这是同步的弊端)
热然异步是 荣联云发送验证码,用户点击用户验证码 ,获取后端接口,
然后celery异步执行, redis存放执行的结果,直接把redis里面把验证码的,
结果取出来,告诉任务就可以了;(任务就是发送验证码)
celery异步执行大大减少了主程序的压力(不会导致主程序堵塞);
把耗时任务放进redis,有任务直接执行;
可能会遇到的报错
报错一 : object has no attribute 'decode'
原因:是没有启动异步项目; 或者是数据库里没有执行的结果信息;取出来的为空;
自然也是不能转码成功了;
解决方法:(celery -A 文件名 worker -l info -P eventlet)
celery -A my_celery.test_celery worker -l info -P eventlet
报错二.添加 这两个字段迁移时 先输入1 ; 然后 输入 timezone.now
created_date = models.DateTimeField(default=now(),verbose_name='注册时间')
last_ogin_data = models.DateTimeField(verbose_name='最后登录时间')
三:.
在视图中连接数据库一定要 用 localhost不能用(127.0.0.1); 不然后报错连接不上redis;
记不住的导包和配置 以及知识盲区 :
1.now 是干啥的
# now表示此时时间;
from django.utils.timezone import now
2.加密查询 和 存储密码
from django.contrib.auth.hashers import make_password,check_password
make_password 加密存储密码 如:
new_pwd = make_password(pwd) 这是对前段传递过来的密码进行加密
check_password 既然是 加密存储; 查询也必须要以这种形式查询密码如:
check_password(pwd, user.password):
3.
构造key从redis中查看执行结果
key = "celery-task-meta-" + resp.id
resp 是调用过来的执行结果
json.loads(json_data) 转化为 dict格式
dict_data['status'] == 'SUCCESS':
SUCCESS 表示执行成功 如果从redis里面取出来的数据 为 SUCCESS 就是执行成功
4.时间戳 表示此时间
TIME_ZONE = 'Asia/ShangHai' (市区; 表示上海时间)
data= time.strftime('%Y-%m-%d')
5.
我自己的荣联云相关配置
accId = '8aaf0708827c8fd50182aabf61dc0867'
accToken = 'f384ebfd51d04bcea1fd1324e7c91acb'
appId = '8aaf0708827c8fd50182aabf62d4086e'
6.
# 存储执行信息
broker_url = 'redis://127.0.0.1:6379/15'
# 结果存储设置(储存执行结果)
result_backend = 'redis://127.0.0.1:6379/14'
7.
# 自动发现项目中所有的任务
有任务就直接执行(这里的任务指的是发送验证码)(第三部)
app.autodiscover_tasks(settings.INSTALLED_APPS)
8.
配置静态资源 STATICFILES_DIRS = ('static',)
9.
启动异步celery
celery -A my_celery.test_celery worker -l info -P eventlet
10.
ElementUI网址
https://element.eleme.cn/#/zh-CN/component/form
安装 element
npm install axios -s element-ui vue-router@3 vuex@3
Element配置:
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
思路整理:
1.他要有一个后缀名 min=(后缀名)
2.在redis里存在执行信息
3.在redis里存放执行结果
4.要投放一个任务;让他来执行
5.要启动任务 (celery -A 文件名 worker -l info -P eventlet)
一 :根目录下 建立utils文件夹:并创将
sms_code.py 文件(本文件是用来和 荣联云做一个连接,让他来帮助
我们生成验证码)
导包:
import random
import redis
import json
from ronglian_sms_sdk import SmsSDK
1.配置荣联云
accId = '8aaf0708827c8fd50182aabf61dc0867'
accToken = 'f384ebfd51d04bcea1fd1324e7c91acb'
appId = '8aaf0708827c8fd50182aabf62d4086e'
2. def语句定义 一个函数
def send_message(mobile):
3 .sdk = SmsSDK(accId, accToken, appId)
4.定义一个变量 tid = '1'
5.导入随机模块生成随机验证码
6.连接数据库 redis.Redis()(默认是0号数据库) 并构造key进行存储
cls.setex("sms_%s"%mobile,300, data) 最以手机号拼接的这种方式进行存储
7.定义变量 里面传递两个参数 datas = (data, '1') 分别是 data表示生成的验证码
1 表示一分钟后过期
8.调用sdk.sendMessage 里面传递 三个参数 (tid, mobile, datas)
分别是 tib变量 和 datas = (data, '1') 变量 与mobile(手机号参数)
9. resp_json = json.loads(resp) return resp_json
将验证码转换为json数据返回
对应代码:
import random
import redis
import json
from ronglian_sms_sdk import SmsSDK
accId = '8aaf0708827c8fd50182aabf61dc0867'
accToken = 'f384ebfd51d04bcea1fd1324e7c91acb'
appId = '8aaf0708827c8fd50182aabf62d4086e'
def send_message(mobile):
sdk = SmsSDK(accId, accToken, appId)
tid = '1'
data = random.randint(100000, 999999)
# 把生成的短信验证码写入redis
cls = redis.Redis()
# redis的数据类型: hash list set zset string
# redis 存放的是:k/v
cls.setex("sms_%s"%mobile,300, data)
datas = (data, '5')
resp = sdk.sendMessage(tid, mobile, datas)
# print("发送短信验证码响应>>>",resp, type(resp))
resp_json = json.loads(resp)
return resp_json
二: 创建 my_celery文件夹 ; 并在文件下创建
test_celery.py文件(这个文件是用来完成 celery 执行异步的三步)
导包:
import os
from celery import Celery (导入celery)
from django.conf import settings
1.导入os 模块 ; 并找到根目录下的manage.py 文件 复制
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'admin.settings')
这一行代码;(作用是设置为全局可用)
INSTALLED_APPS(固定格式) 'admin.settings' = 项目名.setting
2.
给所有的任务添加前缀 app = Celery(main="my_tasks")
3.
app.config_from_object(my_celery.config')
加载配置文件 (这个配置文件就是;把加载信息和返回的结果 分别存入redis)
在 'my_celery 下的 config文件 内写入
(注意不能写为 localhsot)
# 存储执行信息
broker_url = 'redis://127.0.0.1:6379/15'
# 结果存储设置(储存执行结果)
result_backend = 'redis://127.0.0.1:6379/14'
4.
# 自动发现项目中所有的任务
app.autodiscover_tasks(settings.INSTALLED_APPS)
对应代码:
import os
from celery import Celery
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mall_admin_backend.settings')
# 创建celery对象
# main 是给所有任务添加前缀信息
app = Celery(main="my_tasks")
# 加载配置文件
app.config_from_object('my_celery.config')
# 自动发现项目中所有的任务
app.autodiscover_tasks(settings.INSTALLED_APPS)
三:my_celery文件夹下 创建 tasks文件夹下创建
sms_code_tasks.py文件(用来把发送异步验证码生成任务)
导包:
from my_celery.test_celery import app
from utils.sms_code import send_message
1.
@app.task(task)是一个内置的方法
# 使用@app.task
来装饰函数, 把函数变成一个任务 (这个任务指的是发送异步验证码)
2.在函数里面 写成一个方法 传入参数手机号;
调用生成验证码的方法;
把他写进函数里面;表示当做一个任务来执行;
并返回结果
def send_sms_code(mobile):
json_resp = send_message(mobile)
return json_resp
对应代码:
# -*- coding: utf-8 -*-
# @Time : 2022/8/18 14:11
# @Author : zyw
# @Email : panda_kings@163.com
# @File : my_tasks.py
from my_celery.test_celery import app
from utils.sms_code import send_message
# 使用@app.task 来装饰函数, 把函数变成一个任务
@app.task
def send_sms_code(mobile):
json_resp = send_message(mobile)
# print("发送短信验证码的结果是>>>", resp)
return json_resp
1.接收前段的参数
mobile = request.query_params.get('mobile')
2.
resp = send_sms_code.delay(mobile)
调用 执行 验证码 这个方法;
3.
time.sleep(2)
4.
从redis中获取异步任务执行的结果
构造key 把执行结果从redis里面取出来
cls = redis.Redis(host="localhost",port=6379, db=14)
key = "celery-task-meta-" + resp.id
redis_data = cls.get(key)
5.
# 把redis中的数据转码
json_data = redis_data.decode()
6.
dict_data = json.loads(json_data)
把json格式转化为 dict 就像[{status:SUCCESS},{键:值}]这种形式
原本是 "{\"status\": \"SUCCESS\", \"result\}" 这种格式
7.
根据redis里面的执行结果来开判断,执行结果是否成功
来返回响应;
FAILURE 是失败 ; SUCCESS 是成功
if dict_data['status'] == 'FAILURE':
return Response({'message': "短信验证码发送失败", "code": 500})
if dict_data['status'] == 'SUCCESS':
return Response({'message': "短信验证码发送成功", "code": 200})