objects array python flask decorator jsonschema python-decorators

python - array - Frasco: decorador para verificar el esquema JSON y JSON



json schema generator (1)

Tengo una aplicación de matraz con llamadas que esperan carga JSON. Antes de procesar cada llamada, tengo un proceso de verificación de errores de 2 pasos:

  • Asegúrate de que la carga es un JSON válido
  • Asegúrate de que la carga útil JSON cumple con un esquema específico

Que se implementa de la siguiente manera:

@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

Como este código está duplicado en muchas llamadas, me pregunto si puedo moverlo elegantemente a un decorador, algo en la forma de:

@validate_json @validate_schema(schema=app.config[''activate_schema'']) @app.route(''/activate'', methods=[''POST'']) def activate(): ....

El problema es que el argumento de request es implícito: puedo referirme a él dentro de la función, pero no es un parámetro para él. Por lo tanto, no estoy seguro de cómo usarlo en el decorador.

¿Cómo puedo implementar las comprobaciones de validación con los decoradores de Python?


Simplemente use el contexto de request global en su decorador. Está disponible durante cualquier solicitud .

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

Aplique estos decoradores antes de aplicar el decorador @route ; Desea registrar la función envuelta, no la función original para la ruta:

@app.route(''/activate'', methods=[''POST'']) @validate_json @validate_schema(''activate_schema'') def activate(): input = request.json