本系列文章md笔记(已分享)主要讨论django商城项目相关知识。项目利用Django框架开发一套前后端不分离的商城项目(4.0版本)含代码和文档。功能包括前后端不分离,方便SEO。采用Django + Jinja2模板引擎 + Vue.js实现前后端逻辑,Nginx服务器(反向代理)Nginx服务器(静态首页、商品详情页、uwsgi服务器(美多商场业务场景),后端服务:MySQL、Redis、Celery、RabbitMQ、Docker、FastDFS、Elasticsearch、Crontab,外部接口:容联云、QQ互联、支付宝。
全套笔记和代码自取移步gitee仓库: gitee仓库获取完整文档和代码
感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~
共 11 章,132 子模块
图形验证码
图形验证码接口设计和定义
1. 图形验证码接口设计
1.请求方式
|选项|方案| |---|---| |请求方法|GET| |请求地址|image_codes/(?P[\w-]+)/|
2.请求参数:路径参数
|参数名|类型|是否必传|说明| |---|---|---|---| |uuid|string|是|唯一编号|
3.响应结果:
image/jpg
2. 图形验证码接口定义
1.图形验证码视图
```python class ImageCodeView(View): """图形验证码"""
def get(self, request, uuid):""":param request: 请求对象:param uuid: 唯一标识图形验证码所属于的用户:return: image/jpg"""pass
```
2.总路由
```python
verifications
url(r'^', include('verifications.urls')), ```
3.子路由
```python
图形验证码
url(r'^image_codes/(?P [\w-]+)/$', views.ImageCodeView.as_view()), ```
图形验证码后端逻辑
1. 准备captcha扩展包
提示:
captcha
扩展包用于后端生成图形验证码
可能出现的错误
- 报错原因:环境中没有Python处理图片的库:PIL
解决办法
- 安装Python处理图片的库:
pip install Pillow
2. 准备Redis数据库
准备Redis的2号库存储验证码数据
python "verify_code": { # 验证码 "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/2", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } },
3. 图形验证码后端逻辑实现
```python 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
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
```html
- 请填写图形验证码
```
3.图形验证码展示和存储效果
2. Vue实现图形验证码校验
1.register.html
```html
- [[ error_image_code_message ]]
```
2.register.js
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.图形验证码校验效果
短信验证码
短信验证码逻辑分析
知识要点
- 保存短信验证码是为注册做准备的。
- 为了避免用户使用图形验证码恶意测试,后端提取了图形验证码后,立即删除图形验证码。
- Django不具备发送短信的功能,所以我们借助第三方的容联云通讯短信平台来帮助我们发送短信验证码。
容联云通讯短信平台
1. 容联云通讯短信平台介绍
1.容联云官网
- 容联云通讯网址:https://www.yuntongxun.com/
- 注册并登陆
2.容联云管理控制台
3.容联云创建应用
4.应用申请上线,并进行资质认证
5.完成资质认证,应用成功上线
6.添加测试号码
7.短信模板
2. 容联云通讯短信SDK测试
1.模板短信SDK下载
-
https://www.yuntongxun.com/doc/ready/demo/1_4_1_2.html
2.模板短信SDK使用说明
-
http://doc.yuntongxun.com/p/5a533e0c3b8496dd00dce08c
3.集成模板短信SDK
-
CCPRestSDK.py
:由容联云通讯开发者编写的官方SDK文件,包括发送模板短信的方法 ccp_sms.py
:调用发送模板短信的方法
4.模板短信SDK测试
ccp_sms.py
文件中
```python
-- 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返回结果说明
json { 'statusCode': '000000', // 状态码。'000000'表示成功,反之,失败 'templateSMS': { 'smsMessageSid': 'b5768b09e5bc4a369ed35c444c13a1eb', // 短信唯一标识符 'dateCreated': '20190125185207' // 短信发送时间 } }
3. 封装发送短信单例类
1.封装发送短信单例类
```python 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.封装发送短信单例方法
python 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.测试单例类发送模板短信结果
python if __name__ == '__main__': # 注意: 测试的短信模板编号为1 CCP().send_template_sms('17600992168', ['123456', 5], 1)
4. 知识要点
- 容联云通讯只是发送短信的平台之一,还有其他云平台可用,比如,阿里云等,实现套路都是相通的。
- 将发短信的类封装为单例,属于性能优化的一种方案。
短信验证码后端逻辑
1. 短信验证码接口设计
1.请求方式
|选项|方案| |---|---| |请求方法|GET| |请求地址|/sms_codes/(?P1[3-9]\d{9})/|
2.请求参数:路径参数和查询字符串
|参数名|类型|是否必传|说明| |---|---|---|---| |mobile|string|是|手机号| |image_code|string|是|图形验证码| |uuid|string|是|唯一编号|
3.响应结果:JSON
|字段|说明| |---|---| |code|状态码| |errmsg|错误信息|
2. 短信验证码接口定义
```python class SMSCodeView(View): """短信验证码"""
def get(self, reqeust, mobile):""":param reqeust: 请求对象:param mobile: 手机号:return: JSON"""pass
```
3. 短信验证码后端逻辑实现
```python 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
```html
- [[ sms_code_tip ]] [[ error_sms_code_message ]]
```
2.register.js
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.发送短信验证码事件处理
```js 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 { // 4002this.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.接收短信验证码参数
python sms_code_client = request.POST.get('sms_code')
2.保存注册数据之前,对比短信验证码
python 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
```html
- [[ sms_code_tip ]] [[ error_sms_code_message ]] {% if sms_code_errmsg %} {{ sms_code_errmsg }} {% endif %}
```
未完待续, 同学们请等待下一期
全套笔记和代码自取移步gitee仓库: gitee仓库获取完整文档和代码
感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~