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




python-decorators