Python 如何编写带请求的烧瓶装饰器?

Python 如何编写带请求的烧瓶装饰器?,python,flask,python-decorators,Python,Flask,Python Decorators,我不知道为什么下面的decorator[validate_request]不起作用。编写这种验证装饰器的正确方法是什么 def validate_request(req_type): if req_type is 'json' and not request.json: abort(400) def decorator(func): @functools.wraps(func) def wrapped_func(*args, **k

我不知道为什么下面的decorator[validate_request]不起作用。编写这种验证装饰器的正确方法是什么

def validate_request(req_type):
    if req_type is 'json' and not request.json:
        abort(400)
    def decorator(func):
        @functools.wraps(func)
        def wrapped_func(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapped_func
    return decorator

@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT'])
@validate_request('json')
@json
def update_task(task_id):
#    task = filter(lambda t: t['id'] == task_id, tasks)
    task = [task for task in tasks if task['id'] == task_id]
    if len(task) == 0:
        abort(404)

    #update task
    for field in ['title', 'description', 'done']:
        task[0][field] = request.json.get(field, task[0][field])
def验证请求(请求类型):
如果req_类型为“json”而不是request.json:
中止(400)
def装饰器(func):
@functools.wrapps(func)
def wrapped_func(*args,**kwargs):
返回函数(*args,**kwargs)
返回函数
返回装饰器
@app.route('/todo/api/v1.0/tasks/',methods=['PUT'])
@验证请求('json')
@json
def更新任务(任务id):
#任务=筛选器(lambda t:t['id']==task\u id,tasks)
task=[任务中任务的任务,如果任务['id']==任务id]
如果len(任务)==0:
中止(404)
#更新任务
对于['title','description','done']中的字段:
任务[0][field]=request.json.get(字段,任务[0][field])
错误:-

Traceback (most recent call last):
  File "C:\AGR\Programming\LearningPython\FlaskLearning\flask_rest\app.py", line 156, in <module>
    @validate_request('json')
  File "C:\AGR\Programming\LearningPython\FlaskLearning\flask_rest\app.py", line 144, in validate_request
    if req_type is 'json' and not request.json:
  File "C:\Anaconda\lib\site-packages\werkzeug\local.py", line 338, in __getattr__
    return getattr(self._get_current_object(), name)
  File "C:\Anaconda\lib\site-packages\werkzeug\local.py", line 297, in _get_current_object
    return self.__local()
  File "C:\Anaconda\lib\site-packages\flask\globals.py", line 20, in _lookup_req_object
    raise RuntimeError('working outside of request context')
RuntimeError: working outside of request context
回溯(最近一次呼叫最后一次):
文件“C:\AGR\Programming\LearningPython\FlaskLearning\flask\u rest\app.py”,第156行,在
@验证请求('json')
文件“C:\AGR\Programming\LearningPython\FlaskLearning\flask\u rest\app.py”,第144行,在validate\u请求中
如果req_类型为“json”而不是request.json:
文件“C:\Anaconda\lib\site packages\werkzeug\local.py”,第338行,在\uuu getattr中__
返回getattr(self.\u get\u current\u object(),name)
文件“C:\Anaconda\lib\site packages\werkzeug\local.py”,第297行,在\u get\u current\u对象中
返回self.\uuu local()
文件“C:\Anaconda\lib\site packages\flask\globals.py”,第20行,在\u lookup\u req\u对象中
引发运行时错误('在请求上下文之外工作')
运行时错误:在请求上下文之外工作

这应该如何以更惯用的方式完成呢?

这就是你的装饰师应该是什么样子

def validate_request(f):
  @functools.wraps(f)
  def decorated_function(*args, **kwargs):
    # Do something with your request here
    data = flask.request.get_json()
    if not data:
      flask.abort(404)
    return f(*args, **kwargs)
  return decorated_function
你会这样称呼它

@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT'])
@validate_request
def update_task(task_id):
    # The rest of your code..
@app.route('/todo/api/v1.0/tasks/',方法=['PUT']
@验证请求
def更新任务(任务id):
#代码的其余部分。。

这是一篇老文章,但我认为稍加修改可能会对它有所帮助:
函数需要返回
f(*args,**kws)


否则您将遇到
TypeError:view函数未返回有效响应。函数返回None或结束时没有返回语句。

您需要在decorator函数中移动
而不是request.json部分,否则将在decorator应用于视图函数时(即导入时)而不是在调用视图函数时对其进行求值,因此没有可用的请求对象。事实上,如果req_类型为'json'而不是request,只需将整个
放在decororrequest中即可。json已被弃用。无论如何,请使用request.get_json(),到底是什么导致了这里的运行时错误?非常好的捕获,我用内存编写了它,显然它已经溜走了,我希望您不介意在我现有的答案中添加缺少的返回!干杯当然我很高兴我的回答帮助你提高了
def validate_request(f):
  @functools.wraps(f)
  def decorated_function(*args, **kws):
    # Do something with your request here
    data = flask.request.get_json()
    if not data:
      flask.abort(404)
    return f(*args, **kws)
  return decorated_function