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/ 来定义路由规则。举个例子说, 访问 /item/egg, bread 时,你的items 变量将是 ['egg', 'bread']。


@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

规则:如果访问第一个不带后面的斜杠,那么会自动添加一个斜杠,而第二个会返回404.

--------EOF---------
微信分享/微信扫码阅读