Флакон: Декоратор для проверки схемы JSON и JSON
У меня есть флеш-приложение с вызовами, ожидающими полезную нагрузку JSON. Перед обработкой каждого вызова у меня есть двухэтапный процесс проверки ошибок:
- Утвердить, что полезная нагрузка является допустимым JSON
- Предположим, что полезная нагрузка JSON соответствует определенной схеме
Что реализовано следующим образом:
@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
Поскольку этот код дублируется во многих вызовах, мне интересно, могу ли я элегантно переместить его в декоратор, что-то в форме:
@validate_json
@validate_schema(schema=app.config['activate_schema'])
@app.route('/activate', methods=['POST'])
def activate():
....
Проблема в том, что аргумент request
неявный: я могу ссылаться на него внутри функции, но это не параметр для него. Поэтому я не уверен, как использовать его в декораторе.
Как я могу реализовать проверки проверки с помощью декораторов Python?
Ответы
Ответ 1
Просто используйте контекст request
global в вашем декораторе. Он доступен во время любого запроса.
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
Примените эти декораторы перед применением декоратора @route
; вы хотите зарегистрировать завернутую функцию, а не оригинальную функцию для маршрута:
@app.route('/activate', methods=['POST'])
@validate_json
@validate_schema('activate_schema')
def activate():
input = request.json
Ответ 2
Поздний ответ, но вы, вероятно, ищете что-то вроде зефира (фляги-зефира) или жареного зефира.