Einfach ausgedrückt handelt es sich um eine Entwicklungsmethode, bei der zuerst das API-Schema (Definition von Anforderungs- und Antworttypen sowie Feldnamen) ermittelt wird und die Dokumentation und das Modell systematisch zusammen mit dieser generiert werden. Anschließend wird die interne Implementierung durchgeführt. (Referenz: Erläuterung und Implementierungsbeispiel für eine schemagesteuerte Entwicklung zur Optimierung der Team-Web-API-Entwicklung)
Ich möchte eine schemagesteuerte Entwicklung mit Responder durchführen, einem Webframework von Python.
Das Ziel ist es, den folgenden Swagger sehen zu können.
responder Ein modernes Webframework für Python. In Bezug auf das Volumen handelt es sich um ein Mikroframework wie eine Flasche oder eine Flasche. Schreiben Sie einfach Folgendes und führen Sie es wie `` $ python xxx.py``` aus, um den API-Server zu starten, der JSON zurückgibt.
import responder
api = responder.API()
@api.route("/")
async def view(req, resp):
resp.media = {'success': True}
if __name__ == "__main__":
api.run()
Es ist auch bemerkenswert, dass es über moderne Funktionen wie ASGI (Asynchronous Web Server), Websocket, GraphQL und die automatische Generierung von OpenAPI-Schemas verfügt. Ungefähr ein Jahr nach seiner Veröffentlichung ist es ein Monster mit mehr als 3300 Sternen auf Github (Stand November 2019), und die Häufigkeit von Commits ist hoch, daher denke ich, dass es eine gute Zukunft hat.
Referenz:
Die folgenden Entwicklungsmethoden im Responder sind zusammengefasst.
Entspricht dem Kapitel über die Unterstützung offener API-Schemas und die interaktive Dokumentation in der Feature-Tour des Responders (https://responder.readthedocs.io/en/latest/tour.html#openapi-schema-support), ist jedoch bescheiden Da es nur eine Einführung gibt, hätte ich gerne eine praktische Erklärung.
Zur Erläuterung erstellen wir die folgende einfache API.
method | Funktion |
---|---|
get | Gibt alle vorhandenen IDs zurück |
post | Gibt zurück, ob die eingegebene ID vorhanden ist |
Wenn in der Post ein Validierungsfehler auftritt, wird der Fehlerinhalt zurückgegeben.
version responder: v2.0.3 python: v3.6.5
mashmallow ist eine Bibliothek, die die Serialisierung von Objekten unterstützt. Wenn Sie eine Schemaklasse definieren und eine Anforderung oder Antwort über die Schemaklasse laden / sichern, wird die Validierung angewendet. Der Fluss ist wie folgt.
from marshmallow import Schema, fields
class AllIdRespSchema(Schema):
#Schemadefinition(int Liste)
exist_ids = fields.List(fields.Int())
class AllExistIDModel():
#Antwort verspotten
#Ersetzen Sie diesen Inhalt für die spätere Produktion
def __init__(self):
self.exist_ids = [1, 2, 3, 4, 5]
@api.route("/schema_driven")
async def schema_driven_view(req, resp):
if req.method == "get":
# validate response data
resp.media = AllIdRespSchema().dump(AllExistIDModel())
Nach diesem Ablauf werden die für dieses Beispiel erforderliche Schema-Klasse und Mock-Klasse wie folgt definiert. AllIdRespSchema, AllExistIDModel sind im obigen Beispiel definiert.
Schemaname | mock | Verwenden |
---|---|---|
AllIdRespSchema | AllExistIDModel | erhalten Antwort |
IdReqSchema | Keiner | Post Anfrage |
IsExistRespSchema | IsExistIDModel | Antwort nach der Antwort |
ErrorRespSchema | ErrorModel | Antwort auf Validierungsfehler |
class IdReqSchema(Schema):
# if required=True, the field must exist
id = fields.Int(required=True)
class IsExistRespSchema(Schema):
is_exist = fields.Bool()
class ErrorRespSchema(Schema):
error = fields.Str()
errorDate = fields.Date()
class IsExistIDModel():
def __init__(self, data):
id = data.get('id')
self.is_exist = id in [1, 2, 3, 4, 5]
class ErrorModel():
def __init__(self, error):
self.error = str(error)
self.errorDate = datetime.datetime.now()
Wenn Sie Schema auf diese Weise definieren, müssen Sie nur den Prozessablauf für die Ansicht schreiben.
from marshmallow import ValidationError
@api.route("/schema_driven")
async def schema_driven_view(req, resp):
if req.method == "get":
# validate response data
resp.media = AllIdRespSchema().dump(AllExistIDModel())
elif req.method == "post":
request = await req.media()
try:
# validate request data using Schema
data = IdReqSchema().load(request)
except ValidationError as error:
# raise ValidationError
resp.status_code = api.status_codes.HTTP_400
# validate response data
resp.media = ErrorRespSchema().dump(ErrorModel(error))
return
# validate response data
resp.media = IsExistRespSchema().dump(IsExistIDModel(data))
Wie Sie sehen können, wird der Inhalt der Ansicht nur mit dem abstrakten Verarbeitungsablauf und dem Klassennamen für Schema-Klasse und Mock geschrieben. Daher denke ich, dass der Inhalt der Ansicht mit einer kleinen Änderung (Änderung des Typs oder des Feldnamens von json) nicht geändert wird.
Als nächstes möchte ich aus diesem Schema ein Dokument generieren, damit ich Feedback erhalten kann.
Ab hier verwenden wir die Responderfunktion. Es ist jedoch tatsächlich ein Wrapper für eine Bibliothek namens Apispec. Wir lassen nur die Dokumentzeichenfolge und die Schemadefinitionen fast so wie sie sind in die Apispec fließen. Wenn Sie es also im Detail anpassen möchten, müssen Sie sich auf die Definition von Apispec und OpenAPI 3.0 beziehen.
apispec analysiert die Schema-Definition und die Dokumentzeichenfolgen von Marshmallow, wandelt sie in das Open API-Format um und generiert eine Swagger-Benutzeroberfläche.
Referenz:
Zunächst müssen Sie ein Argument hinzufügen, wie unten gezeigt, wenn Sie eine API deklarieren.
api = responder.API(
openapi='3.0.0', # OpenAPI version
docs_route='/docs', # endpoint for interactive documentation by swagger UI. if None, this is not available.
)
Schema Verwenden Sie als Nächstes den Dekorator api.schema, um die Schemadefinition festzulegen. Das Schreiben der Schemadefinition in der Hauptansicht scheint jedoch zu kompliziert zu sein, daher möchte ich die Schemadefinition aus einer anderen Datei importieren. Also werde ich es gewaltsam wie folgt erklären.
api.schema("IdReqSchema")(IdReqSchema)
api.schema("ErrorRespSchema")(ErrorRespSchema)
api.schema("IsExistRespSchema")(IsExistRespSchema)
api.schema("AllIdRespSchema")(AllIdRespSchema)
Wenn Sie den Server starten und auf Folgendes zugreifen, können Sie die Schemadefinition in der Swagger-Benutzeroberfläche wie unten gezeigt überprüfen. 127.0.0.1:5042/docs
API GET Fügen Sie der obigen Ansichtsdefinition einen Dokumentstring im Yaml-Format hinzu, wie unten gezeigt. Sie können die API in der Beschreibung beschreiben. Sie können auch das Antwortschema für jeden Statuscode angeben. Wenn Sie das Schema wie folgt definieren, können Sie auf die Schemadefinition der Antwort und die Beispielantwort von der Swagger-Benutzeroberfläche verweisen. Da Sie beim Verweisen auf die Beispielantwort tatsächlich auf die API zugreifen, können Sie auch überprüfen, ob ein interner Serverfehler auftritt.
@api.route("/schema_driven")
async def schema_driven_view(req, resp):
"""exist id checker endpoint.
---
name: is_exist
get:
description: Get the all exist id
responses:
200:
description: All exist_id to be returned
content:
application/json:
schema:
$ref: "#/components/schemas/AllIdRespSchema"
"""
...
Wenn Sie Swagger aktivieren,
POST Fügen Sie außerdem eine Dokumentzeichenfolge für den Beitrag hinzu. Dies ist in der offiziellen Dokumentation nicht aufgeführt. Weitere Informationen finden Sie unter Open API Definition.
Sie können die Antwort auf die gleiche Weise wie get schreiben. Schreiben wir zwei Statuscodes, 200 (normal) und 400 (Validierungsfehler). Geben Sie außerdem das Anforderungsschema in requestBody an. Sie können den Hauptteil der Anforderung ändern und tatsächlich die API aufrufen.
@api.route("/schema_driven")
async def schema_driven_view(req, resp):
"""exist id checker endpoint.
...
---
post:
description: Check the id exists or not
requestBody:
content:
appliation/json:
schema:
$ref: "#/components/schemas/IdReqSchema"
responses:
200:
description: true/false whether id exists to be returned
content:
application/json:
schema:
$ref: "#/components/schemas/IsExistRespSchema"
400:
description: validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorRespSchema"
"""
Einführung des Verfahrens zur schemagesteuerten Entwicklung mit Responder. Ich bin sehr dankbar, dass Swagger allein damit zu sehen ist. Außerdem hat der Responder viele sehr interessante Funktionen, daher möchte ich verschiedene Dinge ausprobieren!
refs