实验6、Flask API使用示例和拓展
实验介绍
1. 实验内容
Flask 提供了多种API拓展,本节我们主要学习基于RESTful的Flask应用程序设计
2. 实验要点
- 学习和掌握多种RESTful的设计模式
3.实验环境
- Centos 7.9
4. 工作目录
本实验的工作目录为: /experiment
Flask RESTful
我们的Flask RESTful示例应用程序是一种尊重REST体系结构约束的应用程序。但是,它不像协议,开发人员在遵循REST约束的同时实现功能时也很灵活。
现代的Web应用程序允许客户端以无状态的方式在易于阅读且稳定的端点上请求资源。
让我们也在Flask RESTful示例应用程序中以RESTful方式实现一些功能。
我们有一种存储和提供与专辑和歌曲相关的数据的方法。让我们使用Flask RESTful扩展实现API。
启动MongoDB服务
mongod --dbpath /var/lib/mongodb --logpath /var/log/mongodb/mongod.log --fork
首先,使用以下命令安装Flask RESTful。(安装过程已完成,无需再次操作)
pip install flask_restful
为了便于维护和理解,让我们在app目录中创建一个名为api.py
的文件,并在其中提及以下代码行。现在,考虑类似于Flask Views的API。
我们将实现与HTTP动词(get, post, delete)相对应的功能,以在客户端向应用程序的服务器端点发送请求时做出响应。
在app/__init__.py
下添加
from flask import request
from flask_restful import Resource, reqparse, abort, Api
api = Api(app, prefix="/myapi/v1")
def abort_if_song_doesnt_exist(song_name):
if song_name not in SONGS:
abort(404, message="Song {} doesn't exist".format(song_name))
parser = reqparse.RequestParser()
parser.add_argument('title')
parser.add_argument('singer')
SONGS = {
'Song1': {
'title': 'Past Life',
'singer': 'Selena Gomez'
}
}
class Songs(Resource):
def get(self):
return {'songs': SONGS}
def post(self):
args = parser.parse_args(strict=True)
song_name = int(max(SONGS.keys()).lstrip('Song')) + 1
song_name = 'Song%d' % song_name
SONGS[song_name] = {'title': args['title'], 'singer': args['singer']}
return {
song_name: SONGS[song_name]
}, 201
api.add_resource(Songs, '/songs')
class Song(Resource):
def get(self, song_name):
abort_if_song_doesnt_exist(song_name)
return {
song_name: SONGS[song_name]
}
def delete(self, song_name):
abort_if_song_doesnt_exist(song_name)
del SONGS[song_name]
return '', 204
def put(self, song_name):
args = parser.parse_args(strict=True)
abort_if_song_doesnt_exist(song_name)
SONGS[song_name] = {'title': args['title'], 'singer': args['singer']}
return {
song_name: SONGS[song_name]
}, 201
api.add_resource(Song, '/songs/<string:song_name>')
通过将Flask-RESTful的Resource抽象类作为子类,我们创建了两个资源,即Songs和Song。名为Songs的类有两个与两个HTTP动词相对应的get和post方法。分别为GET和POST。
当客户请求时,“Song”资源将所有歌曲提供给已注册的端点,并在将数据发布到同一端点时将歌曲添加到现有歌曲列表中。
同样,对于Song类,使用get,delete和put方法实现HTTP GET,DELETE和PUT。方法get发送请求的歌曲作为JSON的响应,方法delete从SONGS中删除歌曲,而put方法更新SONGS中的现有歌曲。
现在,启动服务器。
安装并使用curl
测试功能
yum install curl
获取songs
curl -k http://localhost:8080/myapi/v1/songs
现在使用下面的命令增添歌曲
curl -k -d "title=Summer Days&singer=Martin Garrix" http://localhost:8080/myapi/v1/songs
如果我们像在上一个命令中一样查询歌曲列表,我们将在响应中得到两首歌曲。
curl -k http://localhost:8080/myapi/v1/songs
需要注意的重要一点是,我们添加的歌曲在运行开发服务器的单个过程中是持久存在的。这意味着该进程关闭后,所有新数据都将丢失。
此外,创建API v1版本的任务似乎是多余的,并且与我们借助表单和视图将数据保存在应用程序中的方式不同。
通常,RESTful API的实现需要从客户端获取数据,在客户端和服务器端之间进行封送处理以及在我们创建的数据库模型的帮助下实现持久性。
此外,可以保护端点以防止意外的输入。
因此,我们建议上述示例仅用于学习使用HTTP方法的REST体系结构的概念和约束。请记住,这只是创建Web服务的多种方式中的一种。此外,有许多方法可以实现REST体系结构。
我们鼓励读者进一步探索REST如何使用其他协议(不仅是JSON和HTTP)具有不同的文件格式和自定义方法。为了让您大致了解一种生产用途,我们提供以下示例。
我们使用Flask-Appbuilder BaseApi在不同的端点下实现类似的功能。打开__init__.py
文件,并使用以下代码进行更新。
from flask import request
from flask_restful import Resource, reqparse, abort
from flask_appbuilder.api import BaseApi, expose
def abort_if_song_doesnt_exist(song_name):
if song_name not in SONGS:
abort(404, message="Song {} doesn't exist".format(song_name))
parser = reqparse.RequestParser()
parser.add_argument('title')
parser.add_argument('singer')
SONGS = {
'Song1': {
'title': 'Past Life',
'singer': 'Selena Gomez'
}
}
class SongsApi(BaseApi):
resource_name = 'songs'
@expose("/", methods=['POST', 'GET'])
def songs(self):
if request.method == 'GET':
return self.response(200, songs=SONGS)
else:
args = parser.parse_args(strict=True)
song_name = int(max(SONGS.keys()).lstrip('Song')) + 1
song_name = 'Song%d' % song_name
SONGS[song_name] = {'title': args['title'], 'singer': args['singer']}
return self.response(201, song=SONGS[song_name])
appbuilder.add_api(SongsApi)
class SongApi(BaseApi):
resource_name = 'songs'
@expose("/<string:song_name>", methods=['GET', 'DELETE', 'PUT'])
def song(self, song_name):
if request.method == 'GET':
abort_if_song_doesnt_exist(song_name)
return self.response(200, song_name=SONGS[song_name])
elif request.method == 'DELETE':
abort_if_song_doesnt_exist(song_name)
del SONGS[song_name]
return self.response(204, message="OK")
elif request.method == 'PUT':
args = parser.parse_args(strict=True)
abort_if_song_doesnt_exist(song_name)
SONGS[song_name] = {'title': args['title'], 'singer': args['singer']}
return self.response(201, song_name=SONGS[song_name])
else:
self.response_404()
appbuilder.add_api(SongApi)
现在我们为其添加测试函数test_api.py
def test_v1_songs(client):
resp = client.get("/api/v1/songs/")
assert 200 == resp.status_code
def test_v1_add_song(client):
data = {
"title": "Summer Days",
"singer": "Martin Garrix"
}
resp = client.post("/api/v1/songs/", data=data)
assert 201 == resp.status_code
输入pytest test_api.py
得到如下结果
Flask-Appbuilder还有助于提供Swagger UI来列出并尝试已发布的API。打开config.py
并使用以下所示的配置对其进行更新。
FAB_API_SWAGGER_UI=True
现在启动服务器并访问到https://localhost:8080/swagge/v1
,您将能够看到Swagger视图,如下所示。
现在,让我们为现有的数据库模型创建API。我们需要使用Flask-Appbuilder的ModelApi。
在__init__.py
内添加为
from flask_appbuilder.api import ModelRestApi
from .models import Song as SongModel
from flask_appbuilder.models.sqla.interface import SQLAInterface
class MySongModelApi(ModelRestApi):
resource_name="newsongs"
datamodel = SQLAInterface(SongModel)
appbuilder.add_api(MySongModelApi)
现在启动服务器并访问到https://localhost:8080/swagge/v1
,您将能够看到Swagger视图,如下所示。
您可以从Swagger视图中尝试使用API,也可以通过将curl发送到端口来进行尝试。
Flask API
Flask API是一个与Django REST框架非常相似的框架。您可以在此处访问Flask API文档。它是Flask框架的直接替代品。
我们可以选择任何上述示例,以在应用程序中实现Flask REST API驱动的功能。
Flask RestPlus
Flask RestPlus
Flask RestPlus是Flask的又一个扩展,可帮助使用Flask创建REST API。该项目已分叉到另一个名为Flask-RESTX的扩展中,并且不再维护。
该项目有大量的装饰器来描述API,并使用Swagger公开其文档。您可以在此处查看该项目的详细信息。
pip install flask_restplus
实验总结
总结
我们借助两个扩展(Flask API和Flask-RESTful)扩展了Flask扩展的概念。
通常,我们都遵循REST体系结构原理和约束来实现RESTful Web服务的规则
在我们的下一个教程中,我们将介绍Django和Flask框架之间的比较,以帮助我们的读者了解这两个框架的优缺点。它还将有助于根据特定项目要求选择一个框架与另一个框架。
常见问题
Q:如何使用Flask创建REST API?
A:我们可以将Flask框架与其他Flask扩展一起使用,例如Flask-RESTful,Flask API,Flask RESTX,Connexion等,以创建基于REST API的Web应用程序。大多数扩展都可以与Flask框架的其他内置功能以及任何其他现有的ORM/Libraries一起使用。
Q:什么是REST API示例?
A:本教程中提供了一个实现RESTFul API的示例应用程序。Flask-RESTful已用于创建示例应用程序。阅读本教程中有关Flask RESTful示例的部分。
Q:RESTful API的用途是什么?
A:一个通常使用HTTP请求并具有HTTP谓词(例如GET,POST,PUT等)的相应后端方法的应用程序编程接口被称为RESTful API。这样的应用程序遵循REST架构原理和约束来实现其功能。
实验6、Flask API使用示例和拓展的更多相关文章
- ASP.NET Web API 开篇示例介绍
ASP.NET Web API 开篇示例介绍 ASP.NET Web API 对于我这个初学者来说ASP.NET Web API这个框架很陌生又熟悉着. 陌生的是ASP.NET Web API是一个全 ...
- 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1
老李推荐:第3章3节<MonkeyRunner源码剖析>脚本编写示例: MonkeyImage API使用示例 在上一节的第一个“增加日记”的示例中,我们并没有看到日记是否真的增加成功 ...
- 老李推荐: 第3章1节《MonkeyRunner源码剖析》脚本编写示例: MonkeyRunner API使用示例
老李推荐: 第3章1节<MonkeyRunner源码剖析>脚本编写示例: MonkeyRunner API使用示例 MonkeyRunner这个类可以说是编写monkeyrunner脚 ...
- HTML 百度地图API调用示例源码
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- Jedis API 详细示例
Jedis API 详细示例 https://www.jianshu.com/p/125357ee7651
- Java8新特性时间日期库DateTime API及示例
Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API ...
- Python Flask API实现方法-测试开发【提测平台】阶段小结(一)
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 本篇主要是对之前几次分享的阶阶段的总结,温故而知新,况且虽然看起来是一个小模块简单的增删改查操作,但其实涉及的内容点是非常的密集的,是非常 ...
- SharePoint 2013 Search REST API 使用示例
前言:在SharePoint2013中,提供Search REST service搜索服务,你可以在自己的客户端搜索方法或者移动应用程序中使用,该服务支持REST web request.你可以使用K ...
- ASP.NET Web API 入门示例详解
REST服务已经成为最新的服务端开发趋势,ASP.NET Web API即为.NET平台的一种轻量级REST架构. ASP.NET Web API直接借鉴了ASP.NET MVC的设计,两者具有非常类 ...
随机推荐
- dubbo服务暴露原理-远程暴露
1.与本地暴露相比,远程暴露也大同小异 我们已经到了第三个关键词Procotol我们来看看他的继承体系图 按照经典图的路线,我们下一个关键词应该就是Server了,从方法名openServer(url ...
- mysql 连表不要用varchar和int这两种不相同的类型做比较
他会默认你123abc等于123 说多了都是泪啊
- 攻防世界(一)baby_web
攻防世界系列:baby_web 方法一: 按照提示,初始界面自然想到index.php,访问后界面(注意到URL)仍是1.php 打开hackbar查看响应,发现确实有index.php点开看到了Fl ...
- http协议工作原理及工作流程
什么是url ? url = 协议 + 域名 + 资源路径 比如: https://www.baidu.com/index.html http : 超文本传输协议 https: 安全套接字协议 HTT ...
- ifconfig显示的网卡信息和我的配置文件名不符
比如我的配置文件, cd /etc/sysconfig/network-scripts/ifcfg-Auto_eth0是这个名称,但是我使用ifconfig显示的信息却是 eth6 Link en ...
- String、Stringbuilder、StringBuffer异同
相同点: String.Stringbuilder.StringBuffer 都可以操作字符串 String 是被final修饰的,容量定长 Stringbuilder 和 Stringbuilder ...
- Python中if name == 'main':的作用
一个python文件通常有两种使用方法, 第一是作为脚本直接执行. 第二是 import 到其它的 python 脚 本中被调用(模块重用)执行. 因此 if name == 'main': 的作用就 ...
- 解决latex数学公式渲染不正确及行内公式中文渲染乱码问题
问题 之前数学OCR渲染数学公式用的 katex 来渲染,前端解决方案,我们的进行公式编写的时候是需要输入中文的,如: Fe_{2}O_{3} + 3 C O \stackrel{高温}{=} 2 F ...
- js--手动实现一个常见的短信验证码输入框
前言 本文记录一下自己手动实现的一个前端常见的短信验证码输入组件,从需求到实现逐步优化的过程. 正文 1.需求分析 首先看一下效果图. 首先页面加载的时候,输入框获取焦点,当用户输入一个数字后,焦点自 ...
- [leetcode] (周赛)869. 重新排序得到 2 的幂
869. 重新排序得到 2 的幂 枚举排列,然后验证.比较暴力. 其实好一点的做法应该反过来,先把int范围下的2的N幂算出来,然后一个一个验证给出的数能不能拼成. class Solution { ...