顺之利

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

无论是Django,还是Flask或者别的web框架的路由的目的都是建立url和函数的对应关系。

对于Flask,他的路由使用装饰器来完成。

最简单的路由

@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello World'
basic_url

route() 装饰器把一个函数绑定到对应的 URL 上。

动态路由

我们经常看到类似http://www.cnblogs.com/yangshl/的url。这里的yangshl是我的博客园的用户名。在Fask中也有带变量的路由。

给 URL 增加变量的部分,把一些特定的字段标记作为参数传入到函数中。当然也可以指定一个可选的转换器通过规则 。

@app.route('/<path:username>/<pid>/hello')
def hello_world(pid, username):
    print("pid", pid)
    print("username", username)
    return 'Hello World!'
View Code

若url是:http://127.0.0.1:8090/kelly/hi/28/hello

则我们截取到

pid 28
username kelly/hi

这说明函数中参数的顺序可以和url中变量的顺序不一致,他们是按照关键字来传参的。而且路由的前后都可以固定的url部分。

其中:path是路由转换器。

实际上Flask有如下几个路由转换器:

  • 'default': <class 'werkzeug.routing.UnicodeConverter'>
  • 'string': <class 'werkzeug.routing.UnicodeConverter'>
  • 'any': <class 'werkzeug.routing.AnyConverter'>
  • 'path': <class 'werkzeug.routing.PathConverter'>
  • 'int': <class 'werkzeug.routing.IntegerConverter'>
  • 'float': <class 'werkzeug.routing.FloatConverter'>
  • 'uuid': <class 'werkzeug.routing.UUIDConverter'>

我们通过url传递的变量都是字符串,可以通过转换器来来进行转换类型和规定它匹配的格式。比如int,若我么传入了abc,则不匹配,会报404错误。

自定义路由转换器。

class RegexConverter(BaseConverter):
    def __init__(self, map, *args):
        self.map = map
        self.regex = args[0]

# 注册转换器
app.url_map.converters['regex'] = RegexConverter

@app.route('/view/<regex("[0-9\.,]+"):uuid>/')
def view(uuid):
  return "view uuid: %s" % (uuid)

再进一步:self.regex到底是什么?
Flask(其实是Werkzeug)使用Converter把URL中特殊部分(<regex("[a-zA-Z0-9]+"):uuid>)转换为Python变量,通用格式是<converter(args):var_name>。在这个例子中,一个叫regex的converter把URL中相应字段转换为view()中的uuid变量。
因此,converter的regex就是用来判断这串字符是否符合转换格式,ok就转换,否则跳过。对于IntegerConverter来说,"abc"显然无能为力。也就是说,其实Werkzeug的路由本来就支持用正则表达式。string、int、float等都是从它派生出来的(可以看看IntegerConverter等built-in Converter的regex)。
至于为什么不显式地支持,我猜可能是因为正则表达式不容易写好,buggy。

反向路由

本质是根据函数名反向生成url,使用函数 url_for() 来针对一个特定的函数构建一个 URL。它能够接受函数名作为第一参数,以及一些关键字参数, 每一个关键字参数对应于 URL 规则的变量部分。未知变量部分被插入到 URL 中作为查询参数。

with app.test_request_context():
  print(url_for('hello_world', username = 'kelly', pid = '12'))

则得到的url是:/kelly/12/hello

若url_for('hello_world', username = 'kelly', pid = '12', _external=True)则返回完整路径:

http://localhost/kelly/12/hello

反向路由在Jinja2中也有使用,用于引入一些静态文件。

 

总之:路由是url和处理函数之间的桥梁。

 

posted on 2017-02-17 00:07  顺之利  阅读(1241)  评论(1编辑  收藏  举报