I have Flask APIs all use phone as optional url parameters as showed below, and I want to use a decorator to verify if the phone number is correct. So can I get the parameter "phone" somewhere without parsing the request url?
@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)
There is a better mechanism to validate url values built in to Werkzeug (and Flask). Define a converter and use it like you would use any other converter in the route (for example, <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
You can also use a before_request
function to validate all routes with a phone argument without having to decorate them all.
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
If you really want to use a decorator, a decorated function gets called with arguments.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With