私はFlask-RESTfulベースのAPIを持っていますが、現在は2つの青写真があり、互換性のない変更でAPIをバージョンアップできます。異なったモデルblueprintsのresource_fields
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表現を定義しています。
特定のリソースフィールドemail
がstring
データタイプからarray[string]
に変更される新しいバージョンのAPIを作成する必要があります。 APIの既存のバージョンでは、元のリソース表現を保持する必要があります。
v1.2
が、それは自分の
resource_fields
定義だが、そうすることで、私はこのエラーで終わることができますように、私はそれぞれの青写真フォルダに
models.py
ファイルを配置しようとしている
:
sqlalchemy.exc.InvalidRequestError: Table '' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.
私はこのことを理解していますすべての青写真について同じデータベーステーブルを本質的に定義しているからです。本当に私が望むのは、データベーススキーマが常にすべてのAPIバージョンで同じになるため、青写真ごとにresource_fields
を変更することだけです。変更可能なJSONレスポンスです。どのように私は青写真あたりresource_fields
を変更することができ、この設定を考えると
(私は新しいフィールドを作成する@property
デコレータを使用しますか)?
以下は、私のプロジェクトのサンプルコードです(簡略化されています)。
アプリ/ 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))
アプリ/ api_1_1 /リソース/ 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) }