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

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

问题描述

我开始用Flask和Python设计一个REST风格的Web服务,我想知道如何在同一个项目中支持多个API版本。
我正在考虑把请求的API版本放在这样的URL中:
$ b

  / myapp / v1 / Users 

经过一段时间,我想在版本1.1中添加另一个端点API和保持从v1没有改变的一切:


$ b

  /myapp/v1.1/Users < =与v1中相同
/myapp/v1.1/Books

In v2 用户-endpoint被改变:

  / myapp / v2 / Users< =已更改in v2 
/ myapp / v2 / Books< =与v1.1相同

等等...



看看

  @ap (版本):
#做某事
返回jsonify(响应)

但我可以想象,每个新的API版本都会更难以维护。因此,我想知道是否有任何更好的(=更容易维护和更好的结构)的方式来实现这一点与Flask?

是你引用的问题的接受答案的作者。我认为 /< version> / users 方法并不是很有效。如果你必须管理三到四个不同的版本,你最终会得到意大利面条代码。

我提出的nginx想法更好,但是有缺点主办两个单独的应用程序。那时我错过了提到第三个选择,那就是为每个API版本使用蓝图。例如,考虑下面的应用程序结构(为了清楚起见,大大简化了):

$ $ $ $ $ c $ 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 路由做出响应。



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

  from api import common 

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

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

 将api作为api_v1导入
从api.v1_1导入api作为api_v1_1
从api.v2导入api作为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

现在,所有这些都说明了,你应该努力设计你的API,使其最小化不得不翻版的风险。考虑到添加新路由不需要新的API版本,用新路由扩展API是完全正确的。现有路线的变化有时可以设计成不影响老客户的方式。有时候,API的转换并不那么痛苦,而且有更多的自由来改变事情,但理想的情况是不会经常发生。


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

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

In v2 the "Users"-endpoint is changed:

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

and so on...

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)

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?

解决方案

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.

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

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.

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()

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')

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.

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.

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

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