在Flask中,添加路由有两种方式:(一般情况下都是用第一种方式)
第一种:常见的装饰器模式
@app.route("/") def index(): return "Hello World"
通过这种方式,将rule与视图函数对应起来
第二种:通过阅读装饰器模式添加路由的源码发现
def route(self, rule, **options): """A decorator that is used to register a view function for a given URL rule. This does the same thing as :meth:`add_url_rule` but is intended for decorator usage:: @app.route('/') def index(): return 'Hello World' For more information refer to :ref:`url-route-registrations`. :param rule: the URL rule as string :param endpoint: the endpoint for the registered URL rule. Flask itself assumes the name of the view function as endpoint :param options: the options to be forwarded to the underlying :class:`~werkzeug.routing.Rule` object. A change to Werkzeug is handling of method options. methods is a list of methods this rule should be limited to (``GET``, ``POST`` etc.). By default a rule just listens for ``GET`` (and implicitly ``HEAD``). Starting with Flask 0.6, ``OPTIONS`` is implicitly added and handled by the standard request handling. """ def decorator(f): endpoint = options.pop("endpoint", None) self.add_url_rule(rule, endpoint, f, **options) return f return decorator
是通过self.add_url_rule这个方式建立起rule与视图函数的对应关系的,所以可以这样添加,
def home(): return "Hello, home!" app.add_url_rule("/home", endpoint=None, view_func=home)
endpoint:给rule起一个别名,相当于django path路由函数中的name。
如何使用通过别名(endpoint)找到rule呢?(如果不起别名,就默认为函数名)
@app.route("/", endpoint="index") def index(): return "Hello World" def home(): from flask import url_for r = url_for("index") # / print(r) return "Hello, home!"
===================================================================================================================================
如何通过路由传递参数呢?<转换器:参数名>
@app.route("/<int:uid>/", endpoint="index") def index(uid): return "Hello {}".format(uid)
常用的转换器:int、float、path、uuid、string、any、default
不难发现,没有正则表达式的转换器,那么我们可以自定义:
1 class RegexConverter(BaseConverter): 2 def __init__(self, map, regex): 3 super(RegexConverter, self).__init__(map) 4 # 为什么只用赋值regex就可以了呢?其他转化器是在类属性regex(正则表达式)的基础上实现的 5 self.regex = regex 6 7 def to_python(self, value): 8 """将提取后的值进行处理""" 9 return value 10 11 def to_url(self, value): 12 """用于反向解析url""" 13 val = super(RegexConverter, self).to_url(value) 14 return val 15 16 17 # 虽然我们已经定制好了正则转换器类,但是应用程序不知道,我们还要通知一下 18 app.url_map.converters["regex"] = RegexConverter 19 20 21 @app.route('/<regex("d+"):uid>/', endpoint="index") 22 def index(uid): 23 return "Hello {}".format(uid)
如何rule里面通过路由传参,那如何反向解析呢?
1 url_for(endpoint, **values)
参数通过**values传递:url_for(endpoint="index", uuid=10)
===================================================================================================================================
app.route方法常见的参数:
rule:URL规则
view_func:视图函数的名称
default:默认值,当URL中无参数,函数需要参数时,使用default={'k':'v'}为函数提供参数
endpoint:名称,用于反向生产URL,即:url_for('名称')
strict_slashes=None:对URL最后的/符号是否严格要求
redirect_to=None:重定向到指定地址
subdomain=None:子域名访问
==================================================================================================================================
路由重点:url、methods、endpoint、int转换器、url_for
==================================================================================================================================
如何给视图函数添加装饰器?
装饰器要放在app.route的下面(放在上面,只会执行一次),并且必须要保留被装饰函数的元信息,因为当我们使用一个装饰器去装饰多个函数时,不保留被装饰函数的元信息,endpoint会默认为函数名,这样就会都等于装饰器函数内部被返回的函数名,导致endpoint重名,会出现错误
1 def showtime(func): 2 def inner(uid): 3 import time 4 print(time.localtime()) 5 res = func(uid) 6 print(time.localtime()) 7 return res 8 return inner 9 10 11 @app.route('/<regex("d+"):uid>/', endpoint="index") 12 @showtime 13 def index(uid): 14 return "Hello {}".format(uid)
为了保留被装饰函数的元信息,必须使用
1 from functools import wraps 2 3 4 def showtime(func): 5 @wraps(func) 6 def inner(uid): 7 import time 8 print(time.localtime()) 9 res = func(uid) 10 print(time.localtime()) 11 return res 12 return inner 13 14 15 @app.route('/<regex("d+"):uid>/', endpoint="index") 16 @showtime 17 def index(uid): 18 return "Hello {}".format(uid)