如何在装饰器中获取Flask的可选URL参数?

5
我有一些Flask API,所有的API都使用手机作为可选的url参数,如下所示。我希望使用一个装饰器来验证电话号码是否正确。那么,我能否在不解析请求url的情况下获取参数“phone”呢?
@user_api.route("/<phone>/login")
@check_phone
def login(phone):
    f = OrderedDict()
    f['error'] = 0
    return jsonify(f)

@user_api.route("/<phone>/logout")
@check_phone
def logout(phone):
    f = OrderedDict()
    f['error'] = 0
    return jsonify(f)
1个回答

9
Werkzeug(和Flask)内置了更好的机制来验证url值。定义一个转换器,并像在路由中使用任何其他转换器一样使用它(例如,<int:id>)。请参见转换器文档
from werkzeug.routing import BaseConverter, ValidationError

class PhoneConverter(BaseConverter):
    regex = r'\d{7,10}'  # this validates the basic form of the value

    def to_python(self, value):
        # do more complicated validation
        if not complicated_phone_validation(value):
            raise ValidationError('not a valid phone number')

        return value

app.url_map.converters['phone'] = PhoneConverter

@app.route('/<phone:phone>')
def get_phone(phone):
    # phone is valid

你还可以使用一个 "before_request" 函数来验证所有带有电话参数的路由,而不必对其进行装饰。
from flask import request, abort

@app.before_request
def valid_phone():
    if 'phone' not in request.view_args:
        return  # view has no phone arg

    if not complicated_phone_validation(request.view_args['phone']):
        abort(404)

@app.route('/<phone>')
def get_phone(phone):
    # phone is valid

@app.route('/<other>')
def get_other(other):
    # no phone arg, no validation

如果你真的想使用装饰器,一个带有装饰器的函数会被传递参数进行调用。

from functools import wraps

def check_phone(f):
    @wraps(f)
    def inner(**kwargs):
        phone = kwargs['phone']
        # do some validation
        return f(**kwargs)

    return inner

@app.route('/<phone>')
@check_phone
def get_phone(phone):
    # phone is valid

    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接