python - Flask: Decorator pour vérifier le schéma JSON et JSON
jsonschema python-decorators (1)
J'ai une application flacon avec des appels en attente de charge utile JSON. Avant que chaque appel soit traité, j'ai un processus de vérification d'erreur en deux étapes:
- Affirmez que la charge utile est un JSON valide
- Affirmer que la charge utile JSON est conforme à un schéma spécifique
Qui est implémenté de la manière suivante:
@app.route('/activate', methods=['POST'])
def activate():
request_id = request.__hash__()
# Assert that the payload is a valid JSON
try:
input = request.json
except BadRequest, e:
msg = "payload must be a valid json"
return jsonify({"error": msg}), 400
# JSON Schema Validation
try:
validate(request.json, app.config['activate_schema'])
except ValidationError, e:
return jsonify({"error": e.message}), 400
Puisque ce code est dupliqué sur de nombreux appels, je me demande si je peux le déplacer élégamment vers un décorateur, quelque chose sous la forme:
@validate_json
@validate_schema(schema=app.config['activate_schema'])
@app.route('/activate', methods=['POST'])
def activate():
....
Le problème est que l'argument request
est implicite: je peux me référer à lui dans la fonction, mais ce n'est pas un paramètre. Par conséquent, je ne suis pas sûr de savoir comment l'utiliser dans le décorateur.
Comment puis-je implémenter les vérifications de validation à l'aide de décorateurs Python?
Utilisez simplement le contexte de request
global dans votre décorateur. Il est disponible lors de toute demande .
from functools import wraps
from flask import (
current_app,
jsonify,
request,
)
def validate_json(f):
@wraps(f)
def wrapper(*args, **kw):
try:
request.json
except BadRequest, e:
msg = "payload must be a valid json"
return jsonify({"error": msg}), 400
return f(*args, **kw)
return wrapper
def validate_schema(schema_name):
def decorator(f):
@wraps(f)
def wrapper(*args, **kw):
try:
validate(request.json, current_app.config[schema_name])
except ValidationError, e:
return jsonify({"error": e.message}), 400
return f(*args, **kw)
return wrapper
return decorator
Appliquez ces décorateurs avant d' appliquer le décorateur @route
; vous voulez enregistrer la fonction enveloppée, pas la fonction d'origine pour l'itinéraire:
@app.route('/activate', methods=['POST'])
@validate_json
@validate_schema('activate_schema')
def activate():
input = request.json