En termes simples, il s'agit d'une méthode de développement qui détermine d'abord le schéma de l'API (définition des types de requête et de réponse et des noms de champ), génère systématiquement des documents et se moque avec lui, puis l'implémente en interne. (Référence: Exemple d'explication et d'implémentation du développement piloté par schéma pour l'optimisation du développement d'API Web d'équipe)
Je voudrais faire du développement piloté par schéma avec responder, qui est un framework web de python.
Le but est de pouvoir voir le Swagger suivant.
responder
Un framework Web moderne pour Python.
En termes de volume, c'est un microframework comme un flacon ou une bouteille.
Écrivez simplement ce qui suit et exécutez-le comme
$ python xxx.py``` pour démarrer le serveur d'API qui renvoie JSON.
import responder
api = responder.API()
@api.route("/")
async def view(req, resp):
resp.media = {'success': True}
if __name__ == "__main__":
api.run()
Il convient également de noter qu'il possède des fonctionnalités modernes telles que le serveur Web asynchrone (ASGI), Websocket, GraphQL et la génération automatique de schéma OpenAPI. Environ un an après sa sortie, c'est un monstre avec plus de 3300 étoiles sur github (en novembre 2019), et la fréquence des commits est élevée, donc je pense qu'il a un bel avenir.
référence:
Les méthodes de développement suivantes dans responder sont résumées.
Correspond au chapitre sur la prise en charge du schéma d'API ouvert et la documentation interactive dans la visite des fonctionnalités du répondeur (https://responder.readthedocs.io/en/latest/tour.html#openapi-schema-support), mais modeste Puisqu'il n'y a qu'une introduction, j'aimerais avoir une explication pratique.
Par souci d'explication, nous allons créer l'API simple suivante.
method | une fonction |
---|---|
get | Renvoie tous les identifiants existants |
post | Renvoie si l'ID entré existe |
De plus, dans la publication, si une erreur de validation se produit, le contenu de l'erreur sera renvoyé.
version responder: v2.0.3 python: v3.6.5
mashmallow est une bibliothèque qui prend en charge la sérialisation des objets. Si vous définissez une classe de schéma et chargez / videz une demande ou une réponse via la classe de schéma, la validation sera appliquée. Le flux est le suivant.
from marshmallow import Schema, fields
class AllIdRespSchema(Schema):
#Définition de schéma(liste int)
exist_ids = fields.List(fields.Int())
class AllExistIDModel():
#réponse simulée
#Remplacez ce contenu pour une production ultérieure
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())
Après ce flux, la classe Schema et la classe fictive requises dans cet exemple sont définies comme suit. AllIdRespSchema, AllExistIDModel sont définis dans l'exemple ci-dessus.
Nom du schéma | mock | Utilisation |
---|---|---|
AllIdRespSchema | AllExistIDModel | avoir une réponse |
IdReqSchema | Aucun | post demande |
IsExistRespSchema | IsExistIDModel | post réponse |
ErrorRespSchema | ErrorModel | Réponse en cas d'erreur de validation |
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()
Si vous définissez le schéma de cette manière, il vous suffit d'écrire le flux de processus pour la vue.
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))
Comme vous pouvez le voir, le contenu de la vue est écrit uniquement avec le flux de traitement abstrait et le nom de classe pour la classe Schema et la maquette. Donc, je pense que le contenu de la vue ne sera pas changé avec un petit changement (changement de type ou de nom de champ de json).
Ensuite, je voudrais générer un document à partir de ce schéma afin que je puisse obtenir des commentaires.
De là, nous utiliserons la fonction répondeur. Cependant, il s'agit en fait d'un wrapper pour une bibliothèque appelée apispec. Tout ce que nous faisons, c'est simplement laisser les définitions de docstring et de schéma couler dans l'apispec presque telles quelles. Donc, si vous souhaitez le personnaliser en détail, vous devez vous référer à la définition d'apispec et d'OpenAPI 3.0.
apispec analyse la définition de schéma et les docstrings de marshmallow, les transforme au format Open API et génère une interface utilisateur Swagger.
référence:
Tout d'abord, vous devez ajouter un argument comme indiqué ci-dessous lors de la déclaration d'une api.
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 Ensuite, utilisez le décorateur api.schema pour définir la définition du schéma. Cependant, écrire la définition de schéma dans la vue principale semble trop compliqué, je voudrais donc importer la définition de schéma à partir d'un autre fichier. Donc, je vais le déclarer de force comme suit.
api.schema("IdReqSchema")(IdReqSchema)
api.schema("ErrorRespSchema")(ErrorRespSchema)
api.schema("IsExistRespSchema")(IsExistRespSchema)
api.schema("AllIdRespSchema")(AllIdRespSchema)
Si vous démarrez le serveur et accédez aux éléments suivants, vous pouvez vérifier la définition du schéma dans l'interface utilisateur de Swagger comme indiqué ci-dessous. 127.0.0.1:5042/docs
API GET Ajoutez la docstring au format yaml à la définition de vue ci-dessus, comme indiqué ci-dessous. Vous pouvez décrire l'API dans la description. Vous pouvez également spécifier le schéma de réponse pour chaque code d'état. Si vous définissez le schéma comme ci-dessous, vous pouvez vous référer à la définition de schéma de la réponse et à l'exemple de réponse de Swagger UI. Étant donné que vous avez atteint l'API lors du référencement de l'exemple de réponse, vous pouvez également vérifier si une erreur de serveur interne se produit.
@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"
"""
...
De même, si vous cochez Swagger,
POST De plus, ajoutez une docstring pour la publication. Cela ne figure pas dans la documentation officielle. Pour plus de détails, vous devez vous référer à Open API Definition.
Vous pouvez écrire une réponse de la même manière que get. Écrivons deux codes d'état, 200 (normal) et 400 (erreur de validation). Spécifiez également le schéma de requête dans requestBody. Vous pouvez modifier le corps de la requête et accéder à l'API.
@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"
"""
Introduction de la procédure de développement piloté par schéma avec le répondeur. Je suis très reconnaissant que Swagger puisse être vu avec cela seul. En plus de cela, responder a beaucoup de fonctionnalités très intéressantes, alors j'aimerais essayer différentes choses!
refs
Recommended Posts