通过项目来深入理解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属性,是一个字典,可以直接取。

  至此,发送短信的接口就算完成了。

posted @ 2018-11-25 20:37  __Miracle  阅读(377)  评论(0编辑  收藏  举报