路由
路由就是根据请求的 url 找到对应处理的函数视图的过程。在请求之前应该建立好一张路由表保存url与视图的对应关系,这样有请求过来才能正确找到对应的视图。
Flask中有两种常用方式构建路由规则:
1、@app.route('url规则') 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 的处理函数,也被称为视图函数
# 装饰器将路由映射到视图index
@app.route('/')
# 定义一个视图
def index():
return 'ok'
#这两种方法是等价的
#app.add_url_rule('/', 'index', index)
查看路由信息
在django中url统一配置在URLconf配置文件中,但是Flask直接配置在视图没有统一的配置文件如何查看路由信息呢?
- app.url_map查看所有路由
示例:
# coding=utf-8
# 导入Flask类
from flask import Flask, current_app
# Flask 接收一个参数__name__,
# 导入模块的目录, flask以这个目录为基础,寻找静态文件目录static和模板目录templates
app = Flask(__name__)
# 装饰器将路由映射到视图index
@app.route('/')
# 定义一个视图
def index():
print(app.url_map)
return 'ok'
if __name__ == '__main__':
# Flask 应用程序实例的方法run启动web服务器
app.run(debug=True)
执行视图会打印出下面url信息:
每一条 Rule对应信息:
- url规则
- 支持的请求方式,默认支持get请求,不支持psot.
- 对应的视图
Map([<Rule '/' (HEAD, GET, OPTIONS) -> index>, <Rule '/static/<filename>' (HEAD, GET, OPTIONS) -> static>])
可以在python shell中导入flask项目查看:
In [5]: from one_day_route import app
In [6]: app.url_map
Out[6]:
Map([<Rule '/' (OPTIONS, HEAD, GET) -> index>,
<Rule '/static/<filename>' (OPTIONS, HEAD, GET) -> static>])
同一路由装饰不同视图
同一个路由规则装饰不同函数,只有第一个视图函数会匹配到。虽然都生成了路由表,但是url匹配中第一个规则之后就会调用视图,不再继续往下匹配。
# 同一个url规则装饰不同的视图函数
@app.route('/index')
def index1():
return 'index1'
@app.route('/index')
def index2():
return 'index2'
一个视图函数多个路由装饰器
同一个视图函数有多个路由装饰器,会生成多条路由信息,每条对应规则的url都可以访问到视图函数。
# 同一个url规则装饰不同的视图函数
@app.route('/index')
@app.route('/index1')
def index1():
print(app.url_map)
return 'index1'
methods 参数
HTTP (与 Web 应用会话的协议)有许多不同的访问 URL 方法。默认情况下,路由只回应 GET 请求,但是通过 route() 装饰器传递 methods 参数可以改变这个行为
methods 参数接收一个字典,元素为字符串形式的请求方式名称。 如果不传methods参数,默认支持 GET, HEAD, OPTIONS
OPTIONS 给客户端提供一个敏捷的途径来弄清这个 URL 支持哪些 HTTP 方法。 从 Flask 0.6 开始,实现了自动处理。
HEAD 浏览器告诉服务器:欲获取信息,但是只关心 消息头 。应用应像处理 GET 请求一样来处理它,但是不分发实际内容。在 Flask 中你完全无需 人工 干预,底层的 Werkzeug 库已经替你打点好了。
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
反向解析
url_for 可以通过视图函数名称,反向解析得到视图对应的url.
url_for函数:
def url_for(endpoint, **values):
pass
@app.route("/python")
def req_python():
return 'python'
@app.route("/url_for")
def req_url():
"""url_for 反向解析"""
return '<a href="%s">链接</a>' % url_for("req_python")
动态路由
要给 URL 添加变量部分,把这些特殊的字段标记为
变量放在\<> 中
@app.route('/param/<name>')
def get_url_param(name):
return '参数是:%s' % name
规则可以用 \
转换器: 默认匹配的是不带/的字符串 int: 接受整数 float:接受浮点数 path: 和默认的相似,但也接受斜线,
# 默认<>的规则匹配不带/的整数
@app.route('/param_int/<int:id>')
def get_url_param_int(id):
return '获取的参数是: %s '% id
# 默认<>的规则匹配不带/的 浮点数
@app.route('/param_float/<float:f>')
def get_url_param_float(f):
return '获取的参数是: %s '% f
# 匹配参数后面带/
@app.route('/param_path/<path:p>')
def get_url_param_path(p):
return '获取的参数是: %s '% p
自定义正则转换器
Flask路由转换器,没有提供基于正则的,但是我们可以自定义基于正则的路由转换器。
- 自定义转换器必须继承BaseConverter类,自定义转换器需要重写父类的init方法
- 注册转换器,url_map中保存了所有的路由转换器,是字典类型
from werkzeug.routing import BaseConverter
# 正则转换器
class RegexConverter(BaseConverter):
def __init__(self, url_map, *args):
# 调用父类的初始化方法
super(RegexConverter, self).__init__(url_map)
# 将正则表达式传给转换器对象,flask在解析路径的时候,会来这里获取regex保存的正则表达式
self.regex = args[0]
def to_python(self, value):
# 对获取到的参数进行处理
# 默认获取到是字符串,可以对获取到的参数进行处理,比如类型转换
# 这样就可以在视图中直接使用
print(type(value))
print(value)
return value
def to_url(self, value):
# 当使用反解析的时候会调用这个方法,可以对参数进行处理
print(value)
return value
# 注册re 转换器 RegexConverter
app.url_map.converters['re'] = RegexConverter
@app.route("/param_re/<re('\d'):num>/<re('\d+'):num2>")
def get_param_re(num, num2):
"""url中提取参数"""
return '自定义正则转换器获取参数1:%s , 参数2:%s' % (num, num2)
@app.route('/get_param_re_url/')
def get_param_url():
"""在视图函数中获取url"""
return '<a href="%s">to_url演示</a>' % (url_for('get_param_re', num='1', num2='2'))