实验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

image

现在使用下面的命令增添歌曲

curl -k -d "title=Summer Days&singer=Martin Garrix" http://localhost:8080/myapi/v1/songs

image

如果我们像在上一个命令中一样查询歌曲列表,我们将在响应中得到两首歌曲。

curl -k http://localhost:8080/myapi/v1/songs

image

需要注意的重要一点是,我们添加的歌曲在运行开发服务器的单个过程中是持久存在的。这意味着该进程关闭后,所有新数据都将丢失。

此外,创建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得到如下结果

image

Flask-Appbuilder还有助于提供Swagger UI来列出并尝试已发布的API。打开config.py并使用以下所示的配置对其进行更新。

FAB_API_SWAGGER_UI=True

现在启动服务器并访问到https://localhost:8080/swagge/v1,您将能够看到Swagger视图,如下所示。

image

现在,让我们为现有的数据库模型创建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视图,如下所示。

image

您可以从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架构原理和约束来实现其功能。

posted @ 2021-05-12 23:04  liuyang9643  阅读(445)  评论(0编辑  收藏  举报