URL篇

在分析路由匹配过程之前,我们先来看看 flask 中,构建这个路由规则的两种方法:

  1. 通过 @app.route() decorator

  2. 通过 app.add_url_rule,这个方法的签名为 add_url_rule(self, rule, endpoint=None, view_func=None, **options),参数的含义如下:

    • rule: url 规则字符串,可以是静态的 /path,也可以包含 /

    • endpoint:要注册规则的 endpoint,默认是 view_func 的名字

    • view_func:对应 url 的处理函数,也被称为视图函数

这两种方法是等价的,也就是说:

@app.route('/')
def hello():
return "hello, world!"

也可以写成

def hello():
return "hello, world!" app.add_url_rule('/', 'hello', hello)

其实,还有一种方法来构建路由规则——直接操作 app.url_map 这个数据结构。不过这种方法并不是很常用,因此就不展开了

静态路由

@app.route('/')
def hello_world():
# 变量可以通过赋值传到前端,前端可以通过Jinja语法{{}}渲染
return render_template('t1.html', name='t1', age=16) @app.route('/services')
def services():
return 'Services'
@app.route('/about')
def about():
return 'About' # 相对projects解释类似于文件夹解释形式,指向某一个文件夹下的某个文件
@app.route('/projects/')
@app.route('/projects_our') # 可以定义多个URL到同一个视图函数上,Flask支持
def projects():
return 'Projects' @app.route('/login',methods=["GET","POST"])
def login():
return render_template('login.html', req_method=request.method)

动态路由

# 动态路由
@app.route('/user/<username>')
def user(username):
print username
return username # 路由转换器:指定参数类型
# flask提供3种:int(整形)|float(浮点型)|path(路径,并支持一个/)
@app.route('/user/<int:user_id>')
def user(user_id):
print user_id
return 'User_id:%s'%user_id

自定义路由规则

# flask不提供正则表达的形式的URL匹配
# 可通过定义完成
# 1、from werkzeug.routing import BaseConverter
# 2、自定义类
#转换器
class RegexConverter(BaseConverter):
def __init__(self,url_map,*items):
super(RegexConverter,self).__init__(self)
# print items # (u'[a-z]{3}[A-Z]{3}',)
# print url_map # URL 的一个MAP对象,类似路由表
self.regex = items[0] # 3、要将定义的类注册到APP的url_map中,定义名称
# app.url_map.converters['regex'] = RegexConverter # 4、使用
@app.route('/user/<regex("[a-z]{3}[A-Z]{3}"):username>')
def user(username):
print username
return 'Username:%s' % username

浅析源码

注册路由规则的时候,flask 内部做了哪些东西呢?我们来看看 route 方法:

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

route 方法内部也是调用 add_url_rule,只不过在外面包了一层装饰器的逻辑,这也验证了上面两种方法等价的说法

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 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) # Methods that should always be added
required_methods = set(getattr(view_func, 'required_methods', ())) # starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling.
provide_automatic_options = getattr(view_func,
'provide_automatic_options', None) if provide_automatic_options is None:
if 'OPTIONS' not in methods:
provide_automatic_options = True
required_methods.add('OPTIONS')
else:
provide_automatic_options = False # Add the required methods now.
methods |= required_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:
old_func = self.view_functions.get(endpoint)
if old_func is not None and old_func != view_func:
raise AssertionError('View function mapping is overwriting an '
'existing endpoint function: %s' % endpoint)
self.view_functions[endpoint] = view_func

add_url_rule

上面这段代码省略了处理 endpoint 和构建 methods 的部分逻辑,可以看到它主要做的事情就是更新 self.url_mapself.view_functions 两个变量。找到变量的定义,发现 url_mapwerkzeug.routeing:Map 类的对象,rulewerkzeug.routing:Rule 类的对象,view_functions 就是一个字典。这和我们之前预想的并不一样,这里增加了 RuleMap 的封装,还把 urlview_func 保存到了不同的地方。

需要注意的是:每个视图函数的 endpoint 必须是不同的,否则会报 AssertionError

未完待续。。。

flask_之URL的更多相关文章

  1. HTML URL地址解析

    通过JavaScript的location对象,可获取URL中的协议.主机名.端口.锚点.查询参数等信息. 示例 URL:http://www.akmsg.com/WebDemo/URLParsing ...

  2. URL安全的Base64编码

    Base64编码可用于在HTTP环境下传递较长的标识信息.在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式.此时,采用Base64编码不仅比较简短,同时也具有不可 ...

  3. Android业务组件化之URL Scheme使用

    前言: 最近公司业务发展迅速,单一的项目工程不再适合公司发展需要,所以开始推进公司APP业务组件化,很荣幸自己能够牵头做这件事,经过研究实现组件化的通信方案通过URL Scheme,所以想着现在还是在 ...

  4. ASP.NET Core的路由[1]:注册URL模式与HttpHandler的映射关系

    ASP.NET Core的路由是通过一个类型为RouterMiddleware的中间件来实现的.如果我们将最终处理HTTP请求的组件称为HttpHandler,那么RouterMiddleware中间 ...

  5. Node.js:path、url、querystring模块

    Path模块 该模块提供了对文件或目录路径处理的方法,使用require('path')引用. 1.获取文件路径最后部分basename 使用basename(path[,ext])方法来获取路径的最 ...

  6. angular2系列教程(十一)路由嵌套、路由生命周期、matrix URL notation

    今天我们要讲的是ng2的路由的第二部分,包括路由嵌套.路由生命周期等知识点. 例子 例子仍然是上节课的例子:

  7. MVC通过路由实现URL重写

    public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Ro ...

  8. 【转】java通用URL接口地址调用方式GET和POST方式

    java通用URL接口地址调用方式GET和POST方式,包括建立请求和设置请求头部信息等等......... import java.io.ByteArrayOutputStream; import ...

  9. linux字符串url编码与解码

    编码的两种方式 echo '手机' | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g' echo '手机' |tr -d '\n' |od -An -tx ...

随机推荐

  1. 10.19-10.20 test

    2016 10.19-10.20 两天  题目by mzx Day1: T1:loverfinding 题解:hash #include<iostream> #include<cst ...

  2. android vector pathData探究,几分钟绘制自己的vectordrawable

    之前经常看到一些酷酷的图标效果, 深入进去发现不是直接用的图片, 而是一些以Vector标签开头的xml文件, 于是就看到了如下代码: <vector xmlns:android="h ...

  3. 编译thrift外篇-关于默认链接包-(使用mapkeeper运行leveldb成功)

    根据 https://stackoverflow.com/questions/9922949/how-to-print-the-ldlinker-search-path 使用 ldconfig -v ...

  4. hdu 6053(To my boyfriend)

    -----------题目链接------------- 题目描述: 给定一个矩阵,定义\(f(A)\) 为矩阵中不同元素的个数.现在要求\(f(A)\)的期望. 解法: 首先来暴力的,复杂度大约:\ ...

  5. 组合优化学习笔记<之>从贪心算法到子集系统再到拟阵

    贪心算法是用的比较多的一种优化算法,因为它过程简洁优美,而且结果有效.有些优化问题如最大权森林(MWF)是可以用贪心问题求解的,由于最小支撑树(MST)问题与MWF是等价的,所以MST也是可以用贪心算 ...

  6. 利用openssl进行base64的编码与解码

    openssl可以直接使用命令对文件件进行base64的编码与解码,利用openssl提供的API同样可以做到这一点. 废话不多说,直接上代码了.需要注意的是通过base64编码后的字符每64个字节都 ...

  7. C# 获取QQ好友列表信息的实现

    分析部分 当我们访问QQ空间的时候,大家可以在右侧的发现一个这样的统计信息  当点击这个链接的时候,会跳转到  这样一个URL 这个URl可以管理好友,当然也就能读取到好友  上面我们是在浏览器中的操 ...

  8. Azure ARM (22) Azure Policy入门

    <Windows Azure Platform 系列文章目录> 我们知道,在Azure服务层级中,分为以下几个层次: 1.企业合同 2.订阅 3.资源组 4.资源 我们使用的Azure资源 ...

  9. hihoCoder2月29日(字符串模拟)

    时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). 只有闰年有2月29日,满足以下一个条件的年份为闰年: ...

  10. android调试之adb

    ADB 其实大部分的PC开发机与Android设备的操作都是通过adb(android debug bridge)技术完成的,这是一个C/S架构的命令行工具,主要由三个部分组成 运行在PC开发机上的命 ...