通过项目来深入理解tornado(四):注册功能实现
通过项目来深入理解tornado(四):注册功能实现
前言
既然短信接口已经搞定了那就来实现一下注册
另外说明一下,这个项目是类似于一个论坛的玩意,主要是写后端代码,因为现在流行前后端分离
测试接口也大部分使用requests库来进行各种请求的模拟
首先需要创建数据表
models.py
from peewee import *
from tornado_bbs.models import BaseModel
from bcrypt import hashpw, gensalt
class PasswordHash(bytes):
def check_password(self, password):
password = password.encode('utf-8')
return hashpw(password, self) == self
class PasswordField(BlobField):
def __init__(self, iterations=12, *args, **kwargs):
if None in (hashpw, gensalt):
raise ValueError('Missing library required for PasswordField: bcrypt')
self.bcrypt_iterations = iterations
self.raw_password = None
super(PasswordField, self).__init__(*args, **kwargs)
def db_value(self, value):
"""Convert the python value for storage in the database."""
if isinstance(value, PasswordHash):
return bytes(value)
if isinstance(value, str):
value = value.encode('utf-8')
salt = gensalt(self.bcrypt_iterations)
return value if value is None else hashpw(value, salt)
def python_value(self, value):
"""Convert the database value to a pythonic value."""
if isinstance(value, str):
value = value.encode('utf-8')
return PasswordHash(value)
GENDER = (
('female', '女'),
('male', '男')
)
class User(BaseModel):
mobile = CharField(max_length=11, verbose_name='手机号', index=True, unique=True)
password = PasswordField(verbose_name='密码')
nick_name = CharField(max_length=20, null=True, verbose_name='昵称')
head_url = CharField(max_length=200, null=True, verbose_name='头像')
address = CharField(max_length=200, null=True, verbose_name='地址')
desc = TextField(verbose_name='描述', null=True, )
gender = CharField(max_length=6, choices=GENDER, null=True, verbose_name='性别')
这里主要是一个password字段的引入,因为在新的peewee里面,移除了password这个字段,所以需要重新翻源码来把它找回来
这里可以找回之前被删除的password字段。
然后创建表
inin_db.py
from tornado_bbs.settings import database
from apps.users.models import User
if __name__ == '__main__':
database.create_tables([User])
这个database是在setting里的
settings.py
import peewee_async
settings = {
'static_path': 'C:/Users/asd47/Desktop/tornado_bbs/static',
'template_path': 'templates',
'db':{
'host': '127.0.0.1',
'user': 'root',
'password': 'root',
'name': 'bbs',
'port': 3306
},
'redis':{
'host': '127.0.0.1',
}
}
database = peewee_async.MySQLDatabase('bbs', host='127.0.0.1', user='root', password='root', port=3306)
因为要使用协程,所以使用peewee_async来代替了peewee
然后配置url之后
就可以开始写注册的逻辑了
handler.py
import json
from .models import User
from tools.yun_pian import YunPian
from .forms import SmsForm, RegisterForm
from tornado_bbs.handler import RedisHandler
from random import choice
class RegisterHandler(RedisHandler):
async def post(self, *args, **kwargs):
params = json.loads(self.request.body.decode('utf8'))
form = RegisterForm.from_json(params)
re_data = {}
if form.validate():
mobile = form.mobile.data
code = form.code.data
password = form.password.data
# 验证码验证
try:
code_result = int(self.redis_conn.get('{}_{}'.format(mobile, code)))
except TypeError as e:
code_result = ''
self.set_status(400)
re_data['code'] = '验证码过期'
if code_result == 1:
valid_code = True
else:
self.set_status(400)
re_data['code'] = '验证码有误'
valid_code = False
# 验证号码是否注册
if valid_code:
result = await self.application.objects.execute(User.select().where(User.mobile == mobile))
if result:
self.set_status(400)
re_data['mobile'] = '用户已经存在'
else:
await self.application.objects.create(User, mobile=mobile, password=password)
self.set_status(201)
else:
self.set_status(400)
for fields in form.errors:
re_data[fields] = form.errors[fields][0]
self.finish(re_data)
上面的坑集:
1.params = json.loads(self.request.body.decode('utf8'))
form = RegisterForm.from_json(params)
这里还是要用from_json,具体原因在上一章中写了。
2.查询数据库是io操作,因此需要await 但是不能直接使用peewee,因为它本身是不支持协程的
所以需要用到之前安装的peewee_async
文档里说明了,需要这样子写
objects = Manager(database) database.set_allow_sync(False) #然后把这个objects加到全局变量里 app.objects = objects
然后就有了如下的操作
await self.application.objects.execute(User.select().where(User.mobile == mobile))
await self.application.objects.create(User, mobile=mobile, password=password)
# 特别说明一下,这里execute后面的语句只是创建了一条sql语句,并没有执行,调用了execute之后才执行
# 另外,这两种方式都可以,execute里面写peewee原来的语句,或者直接用Objects的方法
至此,注册功能就完成了。
总结:
1.密码字段可以去peewee的历史记录找
2.form = RegisterForm.from_json(params),因为框架本身没处理数据,所以需要from_json方法
3.peewee_async需要额外创建Objects对象,并且设置到app里作为全局变量使用

浙公网安备 33010602011771号