如何用 flask 优雅的实现 flask调用restful apii

1228人阅读
Flask(36)
紧接前 4 篇, 继续完成 PUT 和 DELETE 请求的实现.
PUT 请求对应的是资源类的 put() 方法, 表示更新操作. 所以仍然需要先定义 post_put 解析器
vim jmilkfansblog/controllers/flask_restful/parsers.py
post_put_parser = reqparse.RequestParser()
post_put_parser.add_argument(
post_put_parser.add_argument(
post_put_parser.add_argument(
action='append')
post_put_parser.add_argument(
required=True,
help='Auth Token is required to update the posts.')
NOTE: 从 post_put_parser 解析器可以看见, 我们仅允许传入最多 4 个参数, 其中也一定不能缺少 token 以保证数据的安全性.
定义资源类 PostApi 的 put() 更新方法
vim jmilkfansblog/controllers/flask_restful/posts.py
def put(self, post_id=None):
"""Will be execute when receive the HTTP Request Methos `PUT`."""
if not post_id:
abort(400)
post = Post.query.filter_by(id=post_id).first()
if not post:
abort(404)
args = parsers.post_put_parser.parse_args()
user = User.verify_auth_token(args['token'])
if not user:
abort(401)
if user != post.user:
abort(403)
if args['title']:
post.title = args['title']
if args['text']:
post.text = args['text']
if args['tags']:
for item in args['tags']:
tag = Tag.query.filter_by(name=item).first()
post.tags.append(tag)
new_tag = Tag()
new_tag.name = item
post.tags.append(new_tag)
db.session.add(post)
return (post.id, 201)
NOTE: put() 方法和 post() 方法很相似, 所以这里不在赘叙.
DELETE 请求
DELETE 请求的实现是最简单的, 一般而言, 不需要返回任何的数据, 只需要返回正确的 HTTP status_int 就可以了.
vim jmilkfansblog/controllers/flask_restful/posts.py
def delete(self, post_id=None):
"""Will be execute when receive the HTTP Request Method `DELETE`."""
if not post_id:
abort(400)
post = Post.query.filter_by(id=post_id).first()
if not post:
abort(404)
args = parsers.post_delete_parser.parse_args(strict=True)
user = User.verify_auth_token(args['token'])
if user != post.user:
abort(403)
db.session.delete(post)
return "", 204
1 row in set (0.00 sec)
获取 Token
jmilkfan@JmilkFan-Devstack:/opt/JmilkFan-s-Blog$ curl -d "username=&username&" -d "password=&password&" http:
"token": "eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ4MzM2MjExNywiaWF0IjoxNDgzMzYxNTE3fQ.eyJpZCI6IjY1Y2I5NzkyLWI4NzYtNDllNy1iMmM1LTQ2NDY4NjI0MTk5ZSJ9.2r7f-SZJS2U8Zafqyl7oUYPfFGilDJemVwImPuIHxd0"
jmilkfan@JmilkFan-Devstack:/opt/JmilkFan-s-Blog$ curl -X PUT -d "title=Just Test PUT" -d "text=Hello Guys" -d "tags=Python" -d "tags=Flask" -d "token=eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ4MzM2MjExNywiaWF0IjoxNDgzMzYxNTE3fQ.eyJpZCI6IjY1Y2I5NzkyLWI4NzYtNDllNy1iMmM1LTQ2NDY4NjI0MTk5ZSJ9.2r7f-SZJS2U8Zafqyl7oUYPfFGilDJemVwImPuIHxd0" http://localhost:8089/api/posts/1746b650-bcab-436b-82ab-7411e252b576
"-bcab-436b-82ab-"
1 row in set (0.00 sec)
删除一条记录
jmilkfan@JmilkFan-Devstack:/opt/JmilkFan-s-Blog$ curl -X DELETE -d "token=eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ4MzM2MjkzMywiaWF0IjoxNDgzMzYyMzMzfQ.eyJpZCI6IjY1Y2I5NzkyLWI4NzYtNDllNy1iMmM1LTQ2NDY4NjI0MTk5ZSJ9.B8ISY5Fb6AD_PyrJxNVQNYuxXUMrEioB-rlhtyvYcxU" http://localhost:8089/api/posts/1746b650-bcab-436b-82ab-7411e252b576
mysql& select * from posts where id='-bcab-436b-82ab-';
Empty set (0.00 sec)
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:650613次
积分:8870
积分:8870
排名:第2071名
原创:250篇
评论:225条
阅读:8829
文章:37篇
阅读:88088
阅读:8479
文章:13篇
阅读:46357
文章:11篇
阅读:99386
阅读:19638
(1)(1)(2)(5)(5)(5)(12)(11)(27)(10)(11)(15)(24)(22)(8)(3)(4)(15)(5)(24)(29)(10)(6)(2)机器学习算法(8)
Flask-restful API演示
&&& 偶然一次机会看见了国外大神写的Flask框架关于restful api的介绍,链接在此
不得不说,本人最近也在做服务器框架搭建,一直搞不懂,我需要的服务器不需要界面,也就是不需要html解析,也就没有了flask中的render_tempeter这个东东。后来看见这篇文章,感觉特别好,但学完还是有一个疑问,怎么用restful来传输图片,知道将二进制流通过base64转化,但还是不知怎么弄。正在努力学习中。。。
&&& 现在讲学习restful api的过程记录下来。
在此之前,http各种请求方式我就不说了。
如链接文章所说,请求方式为:
http://[hostname]/todo/api/v1.0/
&&& 1.首先搭建简单的flask服务器叫app.py:
&span style=&font-size:14&&#!flask/bin/python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return &Hello, World!&
if __name__ == '__main__':
app.run(debug=True)&/span&这样我们就可以打开浏览器观察浏览器上的内容了。等等,不是说好的不用界面的吗?别着急,下面正式进入RASTful的介绍。
&&& 2.搭建RASTful API服务器
&span style=&font-size:14&&#!flask/bin/python
from flask import Flask, jsonify
app = Flask(__name__)
'id': 1,
'title': u'Buy groceries',
'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
'done': False
'id': 2,
'title': u'Learn Python',
'description': u'Need to find a good Python tutorial on the web',
'done': False
@app.route('/todo/api/v1.0/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
if __name__ == '__main__':
app.run(debug=True)&/span&
&&& 这时,我们就可以使用curl这个工具来测试
&span style=&font-size:14&&curl -i http://localhost:5000/todo/api/v1.0/tasks&/span&
但我们不需要获得整个内容啊,于是我们可以添加参数
&span style=&font-size:14&&from flask import abort
@app.route('/todo/api/v1.0/tasks/&int:task_id&', methods=['GET'])
def get_task(task_id):
task = [task for task in tasks if task['id'] == task_id]
if len(task) == 0:
abort(404)
return jsonify({'task': task[0]})&/span&这里就可以看出来了,在路由选择的时候,添加参数,但如果是二进制呢,参数怎么弄呢?
我们使用下面的命令测试一下:curl -i http://localhost:5000/todo/api/v1.0/tasks/2
如果发现404资源没有找到,我们使用下面的代码友好化:
from flask import make_response
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
&&& 重点来了,使用post来更新服务器:from flask import request
@app.route('/todo/api/v1.0/tasks', methods=['POST'])
def create_task():
if not request.json or not 'title' in request.json:
abort(400)
'id': tasks[-1]['id'] + 1,
'title': request.json['title'],
'description': request.json.get('description', &&),
'done': False
tasks.append(task)
return jsonify({'task': task}), 201
测试一下:curl -i -H &Content-Type: application/json& -X POST -d '{&title&:&Read a book&}' http://localhost:5000/todo/api/v1.0/tasks
到此为止,整个代码已经全部弄好。
希望有朋友如果能够解答上面的问题,能够给我留言,谢谢!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:75807次
积分:1152
积分:1152
排名:千里之外
原创:59篇
评论:16条
(1)(4)(1)(1)(3)(7)(4)(5)(5)(3)(8)(3)(7)(1)(3)(4)(1)使用flask开发RESTful架构的api服务器端(1)–什么是RESTful和为什么选择flask - Python - 伯乐在线
& 使用flask开发RESTful架构的api服务器端(1)–什么是RESTful和为什么选择flask
一、什么是RESTful
最近需要开发一个使用RESTful架构的后台api程序,什么叫RESTful呢,REST的全称是representational state transfer表征状态转移,但其实这个全称也不够完整,它还缺少了主语,什么的表征状态转移呢,资源(resources)的;
资源(resources):
所谓的资源就是网络上的一个实体,它可以使一个图片,一个文本,一个服务,你可以用一个URI指向它,每种资源对应一个特定的URI,要获取这个资源访问它的URI就行了,所谓的上网,其实就是与网络上的资源进行一系列的互动就是了;
表征(representation):
怎么把资源表现出来就是表征的意义,比如一段文本是txt、html还是json,图片是jpg还是png,以http协议为例,就是Accept和content-type中的内容,说明了资源的类型;
状态转移(state tranfer):
访问一个网站,就是客户端和服务端的一个交互过程,客户端想要操作服务端,就必须通过某种手段让服务端的状态发生变化,具体到http协议中就是http的几种方法:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源;
综上所述,什么是RESTful呢?
1、使用URI来表示每一个资源;
2、为每一个资源确定它的表现形式;
3、使用4个方法来操作这些资源;
这样的一个架构就是所谓的RESTful了,看上去非常简单,但是结构确非常清晰,扩展也很方便,非常符合互联网开发的特性。
flask是一个使用python编写轻量级的web应用框架,它非常的简单,但是通过非常丰富的extension能够扩展出很复杂的功能,选用它的理由也很简单,一方面是我用过而且flask确实很容易上手,另一方面是在以往的经验中它的表现非常好。
了解了需求和确定了具体的实现工具后,接下来就是把架子给搭起来再慢慢丰富它的内容了,后面的章节里在一一介绍。
可能感兴趣的话题
o 240 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线& & 最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了。& & 本文将会使用python的Flask框架轻松实现一个RESTful的服务。& & REST的六个特性:& & Client-Server:服务器……
声明:该文章系网友上传分享,此内容仅代表网友个人经验或观点,不代表本网站立场和观点;若未进行原创声明,则表明该文章系转载自互联网;若该文章内容涉嫌侵权,请及时向
论文写作技巧
上一篇:下一篇:
相关经验教程1695人阅读
Flask(36)
构建 RESTful Flask API
为什么要构建 RESTful API ?
对于一个 blog application 而言, 其实完全可以不用到 restful api 也能满足日常所需. 加入 restful api 的唯一目标就是加强该项目的可扩展性, 为后期所要实现的诸如: 博客迁移/数据备份/功能扩展 提供统一且可靠的接口.
定义资源路由
首先我们要有一个大概的需求, 如果希望通过 HTTP 请求来完成对服务端资源的操作, 我们需要解决那些问题?
1. 首先要定位到该资源
2. 告诉服务端我要对该资源做那种操作
3. 前提还可能需要满足身份鉴权(这个需求, 我们后期再实现)
安装 Flask-RESTful
pip install Flask-Restful
pip freeze & requirements.txt
初始化 restful_api 对象
vim jmilkfansblog/extensions.py
from flask.ext.restful import Api
restful_api = Api()
实现 PostApi 资源类
我们将 posts 博客文章定义为一类资源, 只有定义了资源并且对外公开后, 才能被外部所调用.
vim jmilkfansblog/controllers/flask_restful/posts.py
from flask.ext.restful import Resource
class PostApi(Resource):
"""Restful API of posts resource."""
def get(self, post_id=None):
"""Can be execute when receive HTTP Method `GET`.
Will be return the Dict object as post_fields.
return {'hello': 'world'}
NOTE 1: jmilkfansblog/controllers/flask_restful 会作为一个包, 所以要记得创建 __init__.py 文件, 否则无法作为导入路径.
NOTE 2: 每个 REST 资源类都需要继承 flask_restful 的 Resource 类. 其所有的子类都可以通过定义同名实例函数来将该函数绑定到 HTTP Methods 中. EG.
GET &==& get(), 放接受定位到资源的 HTTP GET 方法时, 就会执行该资源类的实例函数 get() .
将 restful_api 对象注册到 app 对象中
vim jmilkfansblog/__init__.py
from jmilkfansblog.extensions import restful_api
from jmilkfansblog.controllers.flask_restful.posts import PostApi
def create_app(object_name):
restful_api.add_resource(
'/api/posts')
restful_api.init_app(app)
NOTE 1: 在 restful_api.add_resource() 指定了资源类 PostApi 所对应的资源名称为 posts, 访问路由为 /api/posts, 这样才完成了对一个资源的完整定义.
NOTE 2: 同时再结合 PostApi 中的 get() 会自动的适配到 HTTP GET 方法, 这样就解决了我们之前所提出的 2 个问题.
现在我们引入一个新的问题, 通过上述定义的 get() 方法我们基本可以获取到数据库 posts 表中的所有记录(当然现在还没有连接数据库操作), 那么如果我只需要获取其中的某一条指定的记录呢?
这里需要在请求中指定 id 来完成单一的定位, 或者也可以传递一个 filters 来过滤若干条满足要求的数据记录.
为资源 posts 添加多条路由
vim jmilkfansblog/__init__.py
def create_app(object_name):
restful_api.add_resource(
'/api/posts',
'/api/posts/&string:post_id&',
endpoint='restful_api_post')
NOTE: add_resource() 允许为同一个资源类绑定多条路由, '/api/posts/&string:post_id&' 表示可以访问 posts 这一类资源中某一个 post_id 一致的资源对象.
为 get() 方法添加 post_id 形参数
vim jmilkfansblog/controllers/flask_restful/posts.py
class PostApi(Resource):
"""Restful API of posts resource."""
def get(self, post_id=None):
"""Can be execute when receive HTTP Method `GET`.
Will be return the Dict object as post_fields.
if post_id:
return {'post_id': post_id}
return {'hello': 'world'}
格式化输出
在上一篇博文中提到, REST 约束要求我们使用一致的数据包装形式来进行响应, 所以我们需要实现一致的格式化功能. 本项目使用最常见的 JSON 格式.
Flask-Restful 的格式化输出, 首先需要定义出一个类似模板的 Dict 类型对象
其 keys 是资源对应的 Model 对象所拥有且需要输出的字段名, values 则声明了该字段的值以何种类型转换并输出. 然后把该字典模板传给装饰器 @marshal_with 并装饰到所有资源类中需要返回数据到客户端的实例方法中. 如此之后,实例方法在返回数据之前都会按照该模板将数据进行格式化转换.
字典模板的 keys 最好与 models 模块中定义的字段名相同, 否则无法自动完成字典模板与 Model 对象的匹配.
vim jmilkfansblog/controllers/flask_restful/posts.py
from flask.ext.restful import Resource, fields, marshal_with
from jmilkfansblog.controllers.flask_restful import fields as jf_fields
nested_tag_fields = {
'id': fields.String(),
'name': fields.String()}
post_fields = {
'author': fields.String(attribute=lambda x: x.user.username),
'title': fields.String(),
'text': jf_fields.HTMLField(),
'tags': fields.List(fields.Nested(nested_tag_fields)),
'publish_date': fields.DateTime(dt_format='iso8601')}
class PostApi(Resource):
"""Restful API of posts resource."""
@marshal_with(post_fields)
def get(self, post_id=None):
"""Can be execute when receive HTTP Method `GET`.
Will be return the Dict object as post_fields.
if post_id:
return {'post_id': post_id}
return {'hello': 'world'}
NOTE 1: 这里需要使用到 flask_restful.fields, 其提供了绝大多数常用的格式类型定义, 具体格式类型列表可以查看官方文档. 当然, 我们也可以自定义一些格式类型, 例如 jf_fields.HTMLField()
NOTE 2: tags 和 author 字段并不存在与 posts 表中, 返回该字段是为了遵守 REST 的约束之一, RESTful API 返回的数据应该尽量满足客户端的需求. 所以我们一般会将表与表之前含有关联关系的字段都一同返回. 格式类型 List 可以接受另外一个格式化输出字典模板对象. 类似于 字典内嵌套字典的格式.
自定义 fields 类型
因为 posts 表中的 text 字段内容是一系列的 HTML 字符串(由 CKEditor 产生), 这些 HTML 字符串是不允许被 RESTful
API 返回的, 因为要满足 REST 的约束之一, 服务端不参与用户界面表现层的业务逻辑(即 HTML 代码), 所以我们需要将该字段值中的 HTML 标签过滤掉.
vim jmilkfansblog/controllers/flask_restful/fields.py
from HTMLParser import HTMLParser
from flask.ext.restful import fields
class HTMLField(fields.Raw):
"""Define a new fields for filter the HTML tags string."""
def format(self, value):
return strip_tags(str(value))
class HTMLStripper(HTMLParser):
"""HTML Parser of Stripper."""
def __init__(self):
self.reset()
self.fed = []
def handle_data(self, data_object):
self.fed.append(data_object)
def get_data(self):
return ''.join(self.fed)
def strip_tags(html):
"""Filter the tags string of HTML for data object of Restful api."""
stripper = HTMLStripper()
stripper.feed(html)
return stripper.get_data()
NOTE 1: 在
fields 模块中通过继承了 flask_restful.fields.Raw 类, 实现了新的格式类型 HTMLField .
NOTE 2: 使用 HTTPParser 来实现 HTML 解析, 重载 handle_data 方法用于将 HTML 标签之间的文本内容合并.
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:650616次
积分:8870
积分:8870
排名:第2071名
原创:250篇
评论:225条
阅读:8829
文章:37篇
阅读:88088
阅读:8479
文章:13篇
阅读:46357
文章:11篇
阅读:99386
阅读:19638
(1)(1)(2)(5)(5)(5)(12)(11)(27)(10)(11)(15)(24)(22)(8)(3)(4)(15)(5)(24)(29)(10)(6)(2)

我要回帖

更多关于 flask开发restful api 的文章

 

随机推荐