2015-03-01 17 views
25

Ich fing an, einen RESTful Webservice mit Flask und Python zu entwerfen und ich frage mich, wie man mehrere API-Versionen im selben Projekt unterstützen würde. Ich denke die angeforderte API-Version in der URL wie folgt der Umsetzung:Unterstützung mehrerer API-Versionen in der Flasche

/myapp/v1/Users 

Nach einiger Zeit habe ich einen anderen Endpunkt in Version 1.1 der API hinzufügen möchten, und halten alles von v1 das nicht ändern:

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

In v2 der "Benutzer" -endpoint wird geändert:

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

und so weiter ...

bei this Frage wahrscheinlich der einfachste Weg suchen würde wie folgt sein:

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

Aber ich kann mir vorstellen, dass dies noch härter werden wird mit jeder neuen API-Version zu erhalten. Deshalb habe ich mich gefragt, ob es einen besseren (= leichter zu wartenden und besser strukturierten) Weg gibt, dies mit Flask zu erreichen?

Antwort

47

Ich bin der Autor der akzeptierten Antwort auf die Frage, auf die Sie verwiesen haben. Ich denke, der Ansatz /<version>/users ist nicht sehr effektiv, wie Sie sagen. Wenn Sie drei oder vier verschiedene Versionen verwalten müssen, werden Sie mit Spaghetti-Code enden.

Die von mir vorgeschlagene nginx-Idee ist besser, hat aber den Nachteil, dass Sie zwei separate Anwendungen hosten müssen. Damals habe ich auf eine dritte Alternative verzichtet, nämlich einen Blueprint für jede API-Version zu verwenden. Betrachten wir zum Beispiel die folgende App-Struktur (stark zur Klarheit vereinfacht):

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

Hier finden Sie eine api/common.py haben, die gemeinsame Funktionen implementiert, dass alle Versionen des API benötigen. Zum Beispiel können Sie eine Hilfsfunktion (nicht als Route eingerichtet) haben, die auf Ihre /users Route antwortet, die in v1 und v1.1 identisch ist.

Die routes.py für jede API-Version definieren die Routen und bei Bedarf Anruf in common.py Funktionen, um doppelte Logik zu vermeiden. Zum Beispiel Ihre v1 und v1.1 routes.py haben kann:

from api import common 

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

Notiere die api.route. Hier ist api ein Blueprint. Wenn Sie jede API-Version als Blueprint implementieren, können Sie alles mit den richtigen versionierten URLs kombinieren. Hier ist ein Beispiel app Setup-Code, der die API-Pläne in die Anwendungsinstanz importiert:

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

Diese Struktur ist sehr schön, weil es alle API-Versionen getrennt hält, aber sie werden von der gleichen Anwendung bedient. Als zusätzlichen Vorteil, wenn die Zeit kommt, nicht mehr zu unterstützen v1, entfernen Sie einfach den register_blueprint Aufruf für diese Version, löschen Sie das v1 Paket aus Ihren Quellen und Sie sind fertig.

Jetzt, mit all dem gesagt, sollten Sie sich wirklich bemühen, Ihre API so zu gestalten, dass das Risiko minimiert wird, die Version zu aktualisieren. Beachten Sie, dass das Hinzufügen neuer Routen keine neue API-Version erfordert. Es ist völlig in Ordnung, eine API um neue Routen zu erweitern.Änderungen an bestehenden Routen können manchmal so gestaltet werden, dass sie alte Clients nicht beeinträchtigen. Manchmal ist es weniger schmerzhaft, die API zu revidieren und mehr Freiheit zu haben, Dinge zu ändern, aber im Idealfall passiert das nicht allzu oft.

+0

Das funktioniert super, vielen Dank! – Keeper

+0

Würde es Ihnen etwas ausmachen, die fehlenden Teile zur Verfügung zu stellen? Wo werden die Blueprints tatsächlich erstellt? In welchen Dateien? Und wie sieht die Blueprint Instanziierung aus? Vielen Dank. – thecountofzero

+0

@thecountofzero Hier ist ein Beispiel API Blueprint, aus meinem Buch: https://github.com/miguelgrinberg/flasky/tree/master/app/api_1_0 – Miguel

Verwandte Themen