Flask路由用法和思想
路由基本用法:
@app.route('/')
def index():
return 'Hello World'
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:: """
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, options)
return f
return decorator
从上面代码可以看到,route实际调用的是add_url_rule,该函数利用werkzeug的MAP和RULE生成路由。在Flask中源码如下:
@setupmethod
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
"""Connects a URL rule. Works exactly like the :meth: route decorator. If a view_func is provided it will be registered with the endpoint.
If the view_func is not provided you will need to connect the endpoint
to a view function like so::
app.view_functions['index'] = index
Internally :meth:`route` invokes :meth:`add_url_rule` so if you want
to customize the behavior via subclassing you only need to change
this method.
: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 view_func: the function to call when serving a request to the
provided endpoint
"""
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options['endpoint'] = endpoint
methods = options.pop('methods', None)
# if the methods are not given and the view_func object knows its
# methods we can use that instead. If neither exists, we go with
# a tuple of only ``GET`` as default.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
if isinstance(methods, string_types):
raise TypeError('Allowed methods have to be iterables of strings, '
'for example: @app.route(..., methods=["POST"])')
methods = set(item.upper() for item in methods)
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
self.url_map.add(rule)
if view_func is not None:
self.view_functions[endpoint] = view_func
self.url_map.add(rule),url_map是一个MAP类,通过该函数会将RUle和MAP绑定.具体函数:
def add(self, rulefactory):
"""Add a new rule or factory to the map and bind it. Requires that the
rule is not bound to another map.
:param rulefactory: a :class:`Rule` or :class:`RuleFactory`
"""
for rule in rulefactory.get_rules(self):
rule.bind(self)
self._rules.append(rule)
self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule)
self._remap = True
-
werkzeug.routing.Rule: A Rule represents one URL pattern.
-
werkzeug.routing.Map: The map class stores all the URL rules and some configuration parameters.
Map里存了许多URL的规则,但是如何与URL关联起来呢?你还需要 werkzeug.routing.MapAdapter。也就是说, URL rule 加入到 Map 中,Map 通过调用 bind 或者 bind_to_environ 返回一个 MapAdapter。MapAdapter 可以使用 match 方法来匹配地址,成功的话,返回 (endpoint, view_arguments),知道了 endpoint 你也 就可以知道对应的 view_fucntion 了。大致的路由情况基本是这样。
例子:
m = Map([ ... Rule('/', endpoint='index'), ... Rule('/downloads/', endpoint='downloads/index'), ... Rule('/downloads/', endpoint='downloads/show') ... ]) urls = m.bind("example.com", "/") urls.match("/", "GET") ('index', {}) urls.match("/downloads/42") ('downloads/show', {'id': 42})
也就是说,我们通过werkzeug的Rule和MAP就可以实现路由的绑定.例子:
from flask import Flask
from werkzeug.routing import Rule, Map
app = Flask(name)
@app.endpoint('index')
def index():
return 'Hello, world.'
url_map = Map([Rule('/', endpoint='index')],)
app.url_map = url_map
上面的endpoint是用来注册函数:
@setupmethod
def endpoint(self, endpoint):
"""A decorator to register a function as an endpoint.
"""
def decorator(f):
self.view_functions[endpoint] = f
return f
return decorator
动态路由规则: 动态路由的URL是可变的,动态路由定义的是一种URL的匹配规则,符合这个路由规则的URL都将指向同一个视函数。
@app.route('/user/')
def user(username):
return 'User %s' % username
动态路由要给 URL 添加变量部分,你可以把这些特殊的字段标记为
这个部分将会作为命名参数传递到你的函数,而且这个部分是必须声明的,如果缺失了 Flask 会产生一个异常。
规则可以用
@app.route('/user/')
def user(user_id):
return 'User %s' % id
转换器有下面几种:
int 接受整数;
float同int ,但是接受浮点数 ; path和默认的相似,但也接受斜线;
Flask的三种转换器可以应对绝大多数的使用场景。我们可以自己构建转换器。
from werkzeug.routing import BaseConverterclass
class ListConverter(BaseConverter):
def to_python(self, value):
return value.split(',')
def to_url(self, values):
return ','.join(BaseConverter.to_url(value)for value in values)
app = Flask(__name__)
app.url_map.converters['list'] = ListConverter
这个时候呢,你可以用 /items/
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
规则:如果访问第一个不带后面的斜杠,那么会自动添加一个斜杠,而第二个会返回404.
微信分享/微信扫码阅读