在flask中支持多个API版本 [英] Support multiple API versions in flask

查看:23
本文介绍了在flask中支持多个API版本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始使用 Flask 和 Python 设计一个 RESTful 网络服务,我想知道如何在同一个项目中支持多个 API 版本.我正在考虑将请求的 API 版本放在 URL 中,如下所示:

I started to design a RESTful webservice with Flask and Python and I'm wondering how one would support multiple API versions in the same project. I'm thinking of putting the requested API version in the URL like this:

/myapp/v1/Users

一段时间后,我想在 API 1.1 版中添加另一个端点,并保留 v1 中未更改的所有内容:

After some time I want to add another endpoint in Version 1.1 of the API and keep everything from v1 which did not change:

/myapp/v1.1/Users   <= Same as in v1
/myapp/v1.1/Books

在 v2 中,用户"端点发生了变化:

In v2 the "Users"-endpoint is changed:

/myapp/v2/Users   <= Changed in v2
/myapp/v2/Books   <= Same as in v1.1

等等...

看着这个 问题最简单的方法可能是这样的:

Looking at this question the easiest way probably would be something like this:

@app.route('/<version>/users')
def users(version):
    # do something
    return jsonify(response)

但我可以想象,随着每个新的 API 版本,这将变得更难维护.因此,我想知道是否有更好的(= 更易于维护和结构更好)的方法来使用 Flask 实现这一目标?

But I can imagine that this will get harder to maintain with each new API version. Therefore I was wondering if there's any better (= easier to maintain and better structured) way to achieve this with Flask?

推荐答案

我是您所引用问题的公认答案的作者.我认为 //users 方法不是很有效.如果您必须管理三个或四个不同的版本,您最终会得到意大利面条式的代码.

I am the author of the accepted answer on the question you referenced. I think the /<version>/users approach is not very effective as you say. If you have to manage three or four different versions you'll end up with spaghetti code.

我在那里提出的 nginx 想法更好,但缺点是您必须托管两个单独的应用程序.当时我没有提到第三种选择,即为每个 API 版本使用蓝图.例如,请考虑以下应用结构(为了清晰起见而进行了极大简化):

The nginx idea I proposed there is better, but has the drawback that you have to host two separate applications. Back then I missed to mention a third alternative, which is to use a blueprint for each API version. For example, consider the following app structure (greatly simplified for clarity):

my_project
+-- api/
    +-- v1/
        +-- __init__.py
        +-- routes.py
    +-- v1_1/
        +-- __init__.py
        +-- routes.py
    +-- v2/
        +-- __init__.py
        +-- routes.py
    +-- __init__.py
    +-- common.py

这里有一个 api/common.py,它实现了所有 API 版本都需要的常用功能.例如,您可以有一个辅助函数(未装饰为路由)来响应在 v1 和 v1.1 中相同的 /users 路由.

Here you have a api/common.py that implements common functions that all versions of the API need. For example, you can have an auxiliary function (not decorated as a route) that responds to your /users route that is identical in v1 and v1.1.

每个 API 版本的 routes.py 定义路由,并在必要时调用 common.py 函数以避免重复逻辑.例如,你的 v1 和 v1.1 routes.py 可以有:

The routes.py for each API version define the routes, and when necessary call into common.py functions to avoid duplicating logic. For example, your v1 and v1.1 routes.py can have:

from api import common

@api.route('/users')
def get_users():
    return common.get_users()

注意api.route.这里 api 是一个蓝图.将每个 API 版本实现为蓝图有助于将所有内容与正确的版本化 URL 结合起来.以下是将 API 蓝图导入应用程序实例的示例应用程序设置代码:

Note the api.route. Here api is a blueprint. Having each API version implemented as a blueprint helps to combine everything with the proper versioned URLs. Here is an example app setup code that imports the API blueprints into the application instance:

from api.v1 import api as api_v1
from api.v1_1 import api as api_v1_1
from api.v2 import api as api_v2

app.register_blueprint(api_v1, url_prefix='/v1')
app.register_blueprint(api_v1_1, url_prefix='/v1.1')
app.register_blueprint(api_v2, url_prefix='/v2')

这种结构非常好,因为它使所有 API 版本保持独立,但它们由同一个应用程序提供服务.作为额外的好处,当需要停止支持 v1 时,您只需删除该版本的 register_blueprint 调用,从源中删除 v1 包即可完成.

This structure is very nice because it keeps all API versions separate, yet they are served by the same application. As an added benefit, when the time comes to stop supporting v1, you just remove the register_blueprint call for that version, delete the v1 package from your sources and you are done.

现在,说了这么多,你真的应该努力设计你的 API,以最大限度地减少必须修订版本的风险.考虑到添加新路由不需要新的 API 版本,使用新路由扩展 API 完全没问题.有时可以以不影响旧客户端的方式设计现有路由的更改.有时,修改 API 不会那么痛苦,并且可以更自由地更改内容,但理想情况下,这种情况不会经常发生.

Now, with all of this said, you should really make an effort to design your API in a way that minimizes the risk of having to rev the version. Consider that adding new routes does not require a new API version, it is perfectly fine to extend an API with new routes. And changes in existing routes can sometimes be designed in a way that do not affect old clients. Sometimes it is less painful to rev the API and have more freedom to change things, but ideally that doesn't happen too often.

这篇关于在flask中支持多个API版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆