Flask理解
之前一直都是用Django开发,换了新工作后,新的公司都是使用Flask+MongoDB,所以目前算初步入门了Flask。
Flask和Django的区别: 一个最明显的区别就是Django把目录结构都限制好了,开发者只需要创建相应的app,再在这个app下编写相应的models.py, views.py等。而Flask呢,仅仅只是实现了web框架最核心的功能(实际就是一个socket服务器,用户的浏览器就是一个socket客户端),有大量的第三方组件,比如ORM框架既可以选flask-sqlalchemy,也可以选flask-mongoengine,可扩展可定制,这是Flask最大的优点了, 通过这些第三方组件的组合,其实Flask也差不多是Django了。
Flask有两个核心依赖库: werkzeug和jinja。其中werkzeug负责核心的逻辑,比如路由,请求和应答的封装等。jinja是负责模板的渲染,如果开发Restful API, 后端返回给前端的只是JSON数据,所以jinja我完全没去了解。
Flask的使用
安装flask
(venv) incisordeMacBook-Pro:flask-test incisor$ pip3 install flask
来一个hello world
app.py文件
from flask import Flask
app = Flask(__name__) # 创建一个实例
@app.route('/')
def hello_world():
return 'hello world'
if __name__ == '__main__':
app.run(debug=True)
通过python3 app.py启动服务器,这个时候去浏览器输入http://127.0.0.1:5000/后,就会看到hello world了。
用Flask来写一个Restful API
Django中如果要写Restful API的话,更多的是使用Django Rest Framework,当然不使用也可以,利用json.dumps()和json.loads()也行。 与Django不同的是,Flask原生就对Restful的支持已经做的很好了,JSON目前是Restful API的主流数据传输方式,Flask可以通过jsonify()将python的dict或list转成JSON。
直接上代码演示吧:
from flask import Flask, request, jsonify
app = Flask(__name__)
# 假设这是数据库存储的数据
USER_LIST = [{'id': 1, 'name': 'zws', 'age': 18}, {'id': 2, 'name': 'Tom', 'age': 19}]
@app.route('/user', methods=['GET'])
def get():
# GET请求获取全部的数据
return jsonify({'code': 200, 'msg': 'ok', 'data': USER_LIST})
if __name__ == '__main__':
app.run(debug=True)
看到这,Flask已经实现了一个Restful API的GET请求,那POST, PUT, PATCH, DELETE是需要在函数里面通过request.method来判断吗?非也,Flask也是有CBV的,接下来用Flask的CBV来改善这个/user这个API。
Flask的CBV需要继承MethodView类
from flask import Flask, jsonify, request
from flask.views import MethodView
app = Flask(__name__)
USER_LIST = [{'id': 1, 'name': 'zws', 'age': 18}, {'id': 2, 'name': 'Tom', 'age': 19}]
class UserView(MethodView):
def get(self):
return jsonify({'code': 200, 'msg': 'ok', 'data': USER_LIST})
def post(self):
# get_json()把前端传来的JSON数据转成Python的dict或者list
json_data = request.get_json()
new_id = len(USER_LIST) + 1
USER_LIST.append({'id': new_id, **json_data})
return jsonify({'code': 204, 'msg': 'ok', 'data': USER_LIST[new_id-1]})
# 注册路由,name参数就是@app.route('/', methods=['GET], endpoint='')中的endpoint
# 这是视图的名字,看了源码后发现,如果不定义endpoint,默认就是当前视图函数的函数名就是endpoint
app.add_url_rule('/user', view_func=UserView.as_view(name='user'))
if __name__ == '__main__':
app.run(debug=True)
json_data = request.get_json()这句代码需要注意,在这里出了个错误。我用postman测试POST请求时,忘记设置Content-Type了,导致request.get_json()返回None,一开始没发现是自己忘记设置Content-Type了,所以首先就直接查看了get_json()的源码:
def get_json(self, force=False, silent=False, cache=True):
...省略...
if not (force or self.is_json):
return None
self.is_json通过判断头部的Content-Type,如果设置了Content-Type: application/json,self.is_json()会返回True,那么这里会有两种处理方式: --> 请求设置Content-Type: application/json --> 请求可以不设置,而把force设置为True (force or self.is_json)其中一个返回True, 就可以了,但是为了规范,还是建议设置请求头的Content-Type,同时也可以在request.get_json()中设置force=True,做两手准备。
从以上代码可以看到利用MethodView就完全可以写Restful API了,
用flask-restful扩展库来写Restful API
flask-restful的官方文档: flask-restfule
安装
pip3 install flask-restful
修改上面的demo:
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
USER_LIST = [{'id': 1, 'name': 'zws', 'age': 18}, {'id': 2, 'name': 'Tom', 'age': 19}]
class UserView(Resource):
def get(self):
# 这里不用再自己手动调用jsonify()了
return {'code': 200, 'msg': 'ok', 'data': USER_LIST}
def post(self):
json_data = request.get_json()
new_id = len(USER_LIST) + 1
USER_LIST.append({'id': new_id, **json_data})
return {'code': 204, 'msg': 'ok', 'data': USER_LIST[new_id-1]}
api.add_resource(UserView, '/user')
if __name__ == '__main__':
app.run(debug=True)
flask-restful的基本使用就是上面这些了,通过继承Resource来实现反射调用get,post这些方法。
打开Resource类,可以看到是继承了MethodView,并且重写了dispatch_request()方法,加入了dict转json的代码,这里就不分析了,因为我也只是大概了看了一下Resource的源码,以后如果详细分析了,再写篇文档吧。
到此,已经可以实现Flask开发Restful API了,经过对比,就能看出比Django轻量多少了,如果学了Django再学Flask,我感觉是分分钟就学完了。