通过项目来深入理解tornado(三):集成短信接口
通过项目来深入理解tornado(三):集成短信接口
前言
在之前已经写好了云片网短信的接口,那么如何集成到项目中来呢
在集成之前,先做好准备工作
urls.py
from tornado.web import URLSpec as url from apps.users.urls import urls as user_url urls = [ ] urls += user_url
users/urls.py
from tornado.web import url
from .handler import SendSms
urls = [
url('/code/', SendSms, name='code'),
]
# Restful api 的规范是url尽量不要出现动词,除非是特殊的如注册或者登录
test.py
import requests
url = 'http://127.0.0.1:8000/code/'
if __name__ == '__main__':
res = requests.post(url, json={'mobile': '17300719720'})
print(res)
forms.py
from wtforms.fields import *
from wtforms.validators import DataRequired, Length
from wtforms_tornado import Form
class SmsForm(Form):
mobile = StringField(validators=[DataRequired(message='手机号码格式不正确'), Length(min=11, max=11, message='手机号码格式不正确')])
这里用到了wtform,一个第三方包
这里有一个坑
from wtforms_tornado import Form 为什么要用这个Form而不是wtform自带的Form呢
因为form = SmsForm(param) 这个,如果传self.request.arguments的话,是不支持的。所以需要用wtforms_tornado这个第三方包,即可解决这个问题.
handler.py
import json
from tornado import web
from tornado.httpclient import HTTPResponse
from tools.yun_pian import YunPian
from .forms import SmsForm
class SendSms(web.RequestHandler):
async def post(self, *args, **kwargs):
param = json.loads(self.request.body.decode('utf8'))
form = SmsForm(param)
if form.validate():
pass
else:
pass
这里就有两个坑
1.通过request.post方法直接传过来的数据,无法通过self.get_arguments()方法获得,需要用self.reqeust.body取到
2.tornado和django这种web框架,都对传过来的数据进行过处理,处理后的数据像这样{‘a’:['b']},但是我们自己接收的数据是原始的字典格式,而验证方法会循环取值,同时字符串又是可迭代类型,所以它只会取到电话号码的第一位。那么如何处理呢,需要用到一个第三方包
pip install wtforms_json
import wtforms_json wtforms_json.init()
随后在服务器启动时候加上这个,然后把form = SmsForm(param)改成form = SmsForm.from_json(param)
它底层是基于猴子补丁的,猴子补丁就是不改变原来代码而新增一些东西。
结果,测试成功!

然后就是集成到项目中了
验证码存在redis中。
import json
from tornado import web
from tools.yun_pian import YunPian
from .forms import SmsForm
from tornado_bbs.handler import RedisHandler
from random import choice
class SendSms(RedisHandler):
def create_code(self):
# 创建四位数短信验证码
seeds = '01234566789'
code = []
for i in range(4):
code.append(choice(seeds))
return ''.join(code)
async def post(self, *args, **kwargs):
param = json.loads(self.request.body.decode('utf8'))
form = SmsForm.from_json(param)
re_data = {}
if form.validate():
# 验证数据
mobile = form.mobile.data
code = self.create_code()
result = await YunPian(mobile).send_single_msg(code)
if result['code'] != 0:
self.set_status(400)
re_data['mobile'] = result['msg']
else:
# 存入redis
self.redis_conn.set('{}_{}'.format(mobile, code), 1, 5*60)
else:
self.set_status(400)
for fields in form.errors:
re_data[fields] = form.errors[fields][0]
这一部分主要是错误信息的提取,一个逻辑是取短信发送后返回的消息里的msg
还一个是表单里如果验证失败又个errors属性,是一个字典,可以直接取。
至此,发送短信的接口就算完成了。

浙公网安备 33010602011771号