创建Flask公共URL装饰器
我想为Flask的路由创建一个装饰器,用来标记某些路由为公开的,这样我就可以像这样做:
@public
@app.route('/welcome')
def welcome():
return render_template('/welcome.html')
在其他地方,我想的装饰器和检查大概是这样的:
_public_urls = set()
def public(route_function):
# add route_function's url to _public_urls
# _public_urls.add(route_function ...?.url_rule)
def decorator(f):
return f
def requested_url_is_public():
from flask import request
return request.url_rule in _public_urls
然后当有请求发出时,我有一个上下文函数来检查requested_url_is_public
。
我有点困惑,因为我不知道如何在public
装饰器中获取给定函数的URL规则。
也许这不是Flask的最佳设计选择,但我觉得应该有其他简单而优雅的方法来实现这个功能。
我之前见过类似的模式,想要模仿一下。例如,这有点像Django的login_required
装饰器。
我很想听听大家对此的看法。
2 个回答
2
我最后做了类似这样的事情:
def public(endpoint):
"""A decorator for endpoints that flags them as publicly accessible
The endpoint is the Flask endpoint function. This is later tested by the
_is_public function, which is called before every request.
Note that @public must come AFTER route.add i.e.
@app.route('...')
@public
def handler(): ...
"""
@wraps(endpoint)
def public_endpoint(*args, **kwargs):
return endpoint(*args, **kwargs)
public_endpoint._is_public = True
return public_endpoint
还有
def _is_public(endpoint):
"""Return true if the given endpoint function is public
Tests whether the @public decorator has been applied to the url.
"""
return getattr(endpoint, '_is_public', False) is True
@blueprint.before_app_request # or @app.before_request
def security_check():
"""Check all incoming requests for a current user.
"""
if current_user.is_logged_in: # need current_user test elsewhere
# we don't need to check if we have a public url if the user is
# logged in
return
try:
if _is_public(current_app.view_functions[request.endpoint]):
# we just go perform the endpoint function if it is public
return
except KeyError:
# There is no endpoint matching the request
abort(404)
# user is not logged in and it's not a public url
logging.info("No current user and %s is not public" % request.path[1:])
# send the user to the welcome page
return redirect(url_for("some_public_page"))
5
Flask已经有一个叫做login_required
的装饰器(你可以查看视图装饰器的相关内容)。如果你是通过public_urls来判断哪些网址需要登录认证,那么使用这个装饰器会更合适。