我有一个基于Flask-RESTful的API,目前有两个蓝图,允许我使用向后不兼容的更改来对API进行版本控制。
from api_1_0 import api_bp as api_1_0_blueprint
app.register_blueprint(api_1_0_blueprint, url_prefix='/api/v1.0')
from api_1_1 import api_bp as api_1_1_blueprint
app.register_blueprint(api_1_1_blueprint, url_prefix='/api/v1.1')
每当我需要进行向后不兼容的更改(例如删除端点)时,我都会创建一个新的蓝图。目前,蓝图共享相同的models.py
文件,定义数据库表和每个模型的JSON表示。
我现在需要创建一个新版本的API,其中特定资源字段email
将从string
数据类型更改为array[string]
。 API的现有版本必须保留原始资源表示。
我尝试在每个蓝图文件夹中放置一个models.py
文件,以便较新的蓝图v1.2
可以拥有自己的resource_fields
定义,但这样做我最终会遇到此错误:
sqlalchemy.exc.InvalidRequestError:已为此MetaData实例定义了表''。将'extend_existing = True'指定为 重新定义现有Table对象上的选项和列。
我理解这种情况正在发生,因为我实质上是为每个蓝图定义相同的数据库表。我真正想要的是改变每个蓝图的resource_fields
,因为所有API版本的数据库模式总是相同的,它只是可能改变的JSON响应。 (我将使用@property
装饰器来创建新字段)
鉴于此设置,如何更改每个蓝图的resource_fields
?
以下是我项目中的一些示例(简化)代码。
app / models.py - https://gist.github.com/MattHealy/4c9d2c03615e3381774235bbbc398437
from app import db
from flask.ext.restful import fields
@swagger.model
class Contact(db.Model):
resource_fields = {
'email': fields.String
}
email = db.Column(db.String(100))
app / api_1_1 / resources / contacts.py - https://gist.github.com/MattHealy/556c93fe33a929e469ae18bf76db83b1
from flask.ext.restful import Resource, marshal, reqparse
from ... models import Contact
class ContactAPI(Resource):
"Retrieve details of a single contact"
@swagger.operation(
nickname = "contact",
responseClass=Contact.__name__,
parameters=[
{
"name": "id",
"description": "ID of the contact",
"required": True,
"allowMultiple": False,
"dataType": "int",
"paramType": "path"
},
],
responseMessages=[
{
"code": 200,
"message": "Contact retrieved"
},
],
summary="Get details of a single contact",
)
def get(self, id):
contact = Contact.query.get(id)
return { 'contact': marshal(contact, Contact.resource_fields) }
答案 0 :(得分:1)
您可以在每个蓝图中使用不同的(本地生成的)resource_fields dict。在您的特定情况下,您可以使用resource_fields作为ContactAPI
类的属性并将其传递给编组函数。
在上面显示的特定情况下(电子邮件字段的类型更改)我认为您还需要构建一个自定义Fields类(基于fields.Raw)以适应您可能想要获得的输出类型。