Flask:用于验证 JSON 和 JSON Schema 的装饰器 [英] Flask: Decorator to verify JSON and JSON Schema
问题描述
我有一个 Flask 应用程序,其调用需要 JSON 有效负载.在处理每个调用之前,我有一个 2 步错误检查过程:
I have a flask application with calls expecting JSON payload. Before each call is processed, I have a 2-step error checking process:
- 断言负载是有效的 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
由于此代码在多次调用中重复,我想知道我是否可以将其优雅地移动到装饰器中,形式为:
Since this code is duplicated over many calls, I wonder If I can elegantly move it to a decorator, something in the formof:
@validate_json
@validate_schema(schema=app.config['activate_schema'])
@app.route('/activate', methods=['POST'])
def activate():
....
问题在于 request
参数是隐式的:我可以在函数中引用它,但它不是它的参数.因此,我不确定如何在装饰器中使用它.
The problem is that the request
argument is implicit: I can refer to it within the function, but it is not a parameter to it. Therefore, I am not sure how to use it within the decorator.
如何使用 Python 装饰器实现验证检查?
推荐答案
只需在装饰器中使用全局 request
上下文即可.它在任何请求期间可用.
Just use the request
context global in your decorator. It is available during any request.
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
装饰器之前应用这些装饰器;您要注册包装函数,而不是路由的原始函数:
Apply these decorators before applying the @route
decorator; you want to register the wrapped function, not the original function for the route:
@app.route('/activate', methods=['POST'])
@validate_json
@validate_schema('activate_schema')
def activate():
input = request.json
这篇关于Flask:用于验证 JSON 和 JSON Schema 的装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!