flask开发restful api系列(2)
继续上一章所讲,上一章我们最后面说道,虽然这个是很小的程序,但还有好几个要优化的地方。先复制一下老的view.py代码。
# coding:utf-8
from flask import Flask, request, jsonify
from model import User, db_session
import hashlib
import time
import redis app = Flask(__name__)
redis_store = redis.Redis(host='localhost', port=6380, db=4, password='dahai123') @app.route('/')
def hello_world():
return 'Hello World!' @app.route('/login', methods=['POST'])
def login():
phone_number = request.get_json().get('phone_number')
password = request.get_json().get('password')
user = User.query.filter_by(phone_number=phone_number).first()
if not user:
return jsonify({'code': 0, 'message': '没有此用户'}) if user.password != password:
return jsonify({'code': 0, 'message': '密码错误'}) m = hashlib.md5()
m.update(phone_number)
m.update(password)
m.update(str(int(time.time())))
token = m.hexdigest() redis_store.hmset('user:%s' % user.phone_number, {'token': token, 'nickname': user.nickname, 'app_online': 1})
redis_store.set('token:%s' % token, user.phone_number)
redis_store.expire('token:%s' % token, 3600*24*30) return jsonify({'code': 1, 'message': '成功登录', 'nickname': user.nickname, 'token': token}) @app.route('/user')
def user():
token = request.headers.get('token')
if not token:
return jsonify({'code': 0, 'message': '需要验证'})
phone_number = redis_store.get('token:%s' % token)
if not phone_number or token != redis_store.hget('user:%s' % phone_number, 'token'):
return jsonify({'code': 2, 'message': '验证信息错误'}) nickname = redis_store.hget('user:%s' % phone_number, 'nickname')
return jsonify({'code': 1, 'nickname': nickname, 'phone_number': phone_number}) @app.route('/logout')
def logout():
token = request.headers.get('token')
if not token:
return jsonify({'code': 0, 'message': '需要验证'})
phone_number = redis_store.get('token:%s' % token)
if not phone_number or token != redis_store.hget('user:%s' % phone_number, 'token'):
return jsonify({'code': 2, 'message': '验证信息错误'}) redis_store.delete('token:%s' % token)
redis_store.hmset('user:%s' % phone_number, {'app_online': 0})
return jsonify({'code': 1, 'message': '成功注销'}) @app.teardown_request
def handle_teardown_request(exception):
db_session.remove() if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5001)
其中验证token的方法,已经重叠了,python教我们,永远不要重复自己的代码,这是很丑陋的行为。今天我们把它换成一个装饰器,然后再把redis调整一下,看看代码会不会简洁很多。
# coding:utf-8
from flask import Flask, request, jsonify
from model import User, db_session
import hashlib
import time
import redis
from functools import wraps app = Flask(__name__)
redis_store = redis.Redis(host='localhost', port=6380, db=4, password='dahai123') def login_check(f):
@wraps(f)
def decorator(*args, **kwargs):
token = request.headers.get('token')
if not token:
return jsonify({'code': 0, 'message': '需要验证'}) phone_number = redis_store.get('token:%s' % token)
if not phone_number or token != redis_store.hget('user:%s' % phone_number, 'token'):
return jsonify({'code': 2, 'message': '验证信息错误'}) return f(*args, **kwargs)
return decorator @app.route('/login', methods=['POST'])
def login():
phone_number = request.get_json().get('phone_number')
password = request.get_json().get('password')
user = User.query.filter_by(phone_number=phone_number).first()
if not user:
return jsonify({'code': 0, 'message': '没有此用户'}) if user.password != password:
return jsonify({'code': 0, 'message': '密码错误'}) m = hashlib.md5()
m.update(phone_number)
m.update(password)
m.update(str(int(time.time())))
token = m.hexdigest() pipeline = redis_store.pipeline()
pipeline.hmset('user:%s' % user.phone_number, {'token': token, 'nickname': user.nickname, 'app_online': 1})
pipeline.set('token:%s' % token, user.phone_number)
pipeline.expire('token:%s' % token, 3600*24*30)
pipeline.execute() return jsonify({'code': 1, 'message': '成功登录', 'nickname': user.nickname, 'token': token}) @app.route('/user')
@login_check
def user():
token = request.headers.get('token')
phone_number = redis_store.get('token:%s' % token) nickname = redis_store.hget('user:%s' % phone_number, 'nickname')
return jsonify({'code': 1, 'nickname': nickname, 'phone_number': phone_number}) @app.route('/logout')
@login_check
def logout():
token = request.headers.get('token')
phone_number = redis_store.get('token:%s' % token) pipeline = redis_store.pipeline()
pipeline.delete('token:%s' % token)
pipeline.hmset('user:%s' % phone_number, {'app_online': 0})
pipeline.execute()
return jsonify({'code': 1, 'message': '成功注销'}) @app.teardown_request
def handle_teardown_request(exception):
db_session.remove() if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5001)
加了一个装饰器,是不是简洁了很多?每次需要验证的时候,只需要一个login_check就可以了,这样就变得非常简洁,而且脉络清晰。redis也改成了管道执行,pipeline,防止执行到一半,被掐断。
可是,可是,我还是觉得不简洁,看user, logout的代码中重复的地方。
token = request.headers.get('token')
phone_number = redis_store.get('token:%s' % token)
每次都有这两句,要是将来还有其他值怎么办?上面不刚说,永远不要重复自己的代码吗?
好,我们再写一个函数,看下面代码
# coding:utf-8
from flask import Flask, request, jsonify, g
from model import User, db_session
import hashlib
import time
import redis
from functools import wraps app = Flask(__name__)
redis_store = redis.Redis(host='localhost', port=6380, db=4, password='dahai123') def login_check(f):
@wraps(f)
def decorator(*args, **kwargs):
token = request.headers.get('token')
if not token:
return jsonify({'code': 0, 'message': '需要验证'}) phone_number = redis_store.get('token:%s' % token)
if not phone_number or token != redis_store.hget('user:%s' % phone_number, 'token'):
return jsonify({'code': 2, 'message': '验证信息错误'}) return f(*args, **kwargs)
return decorator @app.before_request
def before_request():
token = request.headers.get('token')
phone_number = redis_store.get('token:%s' % token)
if phone_number:
g.current_user = User.query.filter_by(phone_number=phone_number).first()
g.token = token
return @app.route('/login', methods=['POST'])
def login():
phone_number = request.get_json().get('phone_number')
password = request.get_json().get('password')
user = User.query.filter_by(phone_number=phone_number).first()
if not user:
return jsonify({'code': 0, 'message': '没有此用户'}) if user.password != password:
return jsonify({'code': 0, 'message': '密码错误'}) m = hashlib.md5()
m.update(phone_number)
m.update(password)
m.update(str(int(time.time())))
token = m.hexdigest() pipeline = redis_store.pipeline()
pipeline.hmset('user:%s' % user.phone_number, {'token': token, 'nickname': user.nickname, 'app_online': 1})
pipeline.set('token:%s' % token, user.phone_number)
pipeline.expire('token:%s' % token, 3600*24*30)
pipeline.execute() return jsonify({'code': 1, 'message': '成功登录', 'nickname': user.nickname, 'token': token}) @app.route('/user')
@login_check
def user():
user = g.current_user nickname = redis_store.hget('user:%s' % user.phone_number, 'nickname')
return jsonify({'code': 1, 'nickname': nickname, 'phone_number': user.phone_number}) @app.route('/logout')
@login_check
def logout():
user = g.current_user pipeline = redis_store.pipeline()
pipeline.delete('token:%s' % g.token)
pipeline.hmset('user:%s' % user.phone_number, {'app_online': 0})
pipeline.execute()
return jsonify({'code': 1, 'message': '成功注销'}) @app.teardown_request
def handle_teardown_request(exception):
db_session.remove() if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5001)
我们在代码中加了一个before_request,这个函数就是在每个request发起的时候,如果已经验证了,我们把当前g.current_user和g.token设置一下,这样每次需要获取当前用户的时候,直接找g.current_user就可以了,是不是简单了太多太多?好了,今天到此为止,下一章,我们讲怎么利用alembic修改数据库。
flask开发restful api系列(2)的更多相关文章
- flask开发restful api系列(8)-再谈项目结构
上一章,我们讲到,怎么用蓝图建造一个好的项目,今天我们继续深入.上一章中,我们所有的接口都写在view.py中,如果几十个,还稍微好管理一点,假如上百个,上千个,怎么找?所有接口堆在一起就显得杂乱无章 ...
- flask开发restful api系列(1)
在此之前,向大家说明的是,我们整个框架用的是flask + sqlalchemy + redis.如果没有开发过web,还是先去学习一下,这边只是介绍如果从开发web转换到开发移动端.如果flask还 ...
- flask开发restful api系列(7)-蓝图与项目结构
如果有几个原因可以让你爱上flask这个极其灵活的库,我想蓝图绝对应该算上一个,部署蓝图以后,你会发现整个程序结构非常清晰,模块之间相互不影响.蓝图对restful api的最明显效果就是版本控制:而 ...
- flask开发restful api系列(6)-配置文件
任何一个好的程序,配置文件必不可少,而且非常重要.配置文件里存储了连接数据库,redis的用户密码,不允许有任何闪失.要有灵活性,用户可以自己配置:生产环境和开发环境要分开,最好能简单的修改一个东西, ...
- flask开发restful api系列(5)-短信验证码
我们现在开发app,注册用户的时候,不再像web一样,发送到个人邮箱了,毕竟个人邮箱在移动端填写验证都很麻烦,一般都采用短信验证码的方式.今天我们就讲讲这方面的内容. 首先,先找一个平台吧.我们公司找 ...
- flask开发restful api系列(4)--七牛图片服务
上一章我们讲到如何利用alembic来更新数据库,这章,我们讲如何通过七牛服务来存储图片. 像我们大多数公司一样,公司资金比较少,如果自己开发图片服务器,代价太大:如果我们用自己的网站服务器来保存图片 ...
- flask开发restful api系列(3)--利用alembic进行数据库更改
上面两章,主要讲基本的配置,今天我们来做一个比较有趣的东西,为每个客户加一个头像图片.如果我们图片保存在自己的服务器,对于服务器要求有点高,每次下载的时候,都会阻塞网络接口,要是1000个人同时访问这 ...
- flask开发restful api
flask开发restful api 如果有几个原因可以让你爱上flask这个极其灵活的库,我想蓝图绝对应该算上一个,部署蓝图以后,你会发现整个程序结构非常清晰,模块之间相互不影响.蓝图对restfu ...
- 描述怎样通过flask+redis+sqlalchemy等工具,开发restful api
flask开发restful api系列(8)-再谈项目结构 摘要: 进一步介绍flask的项目结构,使整个项目结构一目了然.阅读全文 posted @ 2016-06-06 13:54 月儿弯弯02 ...
随机推荐
- 01 - 概述 VTK 6.0 迁移
摘要 对vtk版本4和5的管道机制重新架架构的主要目的是:迁移数据对象和算法对象中的管道执行逻辑到一个新集合的类中,我们称这个集合类叫executives.分离数据和执行模型的代码后,可以双双简化修改 ...
- 形形色色的软件生命周期模型(4)——MSF、实用型
摘要: 读大学时,我们曾经学习过不少软件生命周期模型,当时还不是很懂软件开发,你可能会觉得这些东西很新奇.在实际工作中,你会发现这些模型其实很难应用,与此同时你会接触到RUP.MSF等权威软件公司的生 ...
- POJ 2886 Who Gets the Most Candies? 线段树。。还有方向感
这道题不仅仅是在考察线段树,还他妹的在考察一个人的方向感.... 和线段树有关的那几个函数写了一遍就对了,连改都没改,一直在转圈的问题的出错.... 题意:从第K个同学开始,若K的数字为正 则往右转, ...
- 【Ruby on Rails 学习一】ubuntu14.04配置rvm与ruby
要安装ruby,首先要安装rvm,借助rvm安装ruby rvm 的全称是 Ruby Version Manager ,是一款由 Wayne E. Seguin 开发的一款命令行工具.rvm 能够让 ...
- Python 2 到 Python 3的变化
Python 2.x到Python 3.x变化还是挺大的,具体的变化,参考官方文档: https://docs.python.org/3.0/whatsnew/3.0.html
- js基础例子动态创建table实例
<style> table{ width:500px; font-weight: bold; border: 1px solid #000; border-collapse:collaps ...
- (转)How to build an Apple Push Notification provider server (tutorial)
转自:https://blog.serverdensity.com/how-to-build-an-apple-push-notification-provider-server-tutorial/ ...
- String 和 InputStream 互转方式
/** * 利用BufferedReader实现Inputstream转换成String <功能详细描述> * * @param in * @return String */ public ...
- Github 开源编辑器 ATOM 已开放下载
Update:2014-09-08 Atom 于5月6日正式开放下载(遗憾的是只有 MAC 版本),并且在 MIT 协义下开源,从界面可以看出,这款软件很像 Sublime Text,不过由于她的开源 ...
- android之字体阴影效果
今天刚刚好做了个字体阴影的效果,感觉加上了阴影的效果立体感十足啊!写了个简单的demo与大家分享下!主要是以下四个属性 android:shadowColor 阴影的颜色 android:shad ...