本文重点介绍,Flask路由分发及访问静态资源。
app.route
装饰器的作用是将路由映射到视图函数,从浏览器输入对应的url
地址,Flask程序,就会根据url
找到对应的视图函数(View Function)
进行处理。视图函数名字可以与url
不同。route
装饰器内部会调用add_url_route()
方法实现路由注册。
"""
Author: hui
Desc: { Flask 路由分发 }
"""
from flask import Flask, url_for, redirect
"""
# 创建flask的应用对象
# __name__表示当前的模块名字
"""
app = Flask(__name__)
@app.route("/hello")
def welcome():
return "hello flask"
@app.route("/index")
def index():
return "index page"
if __name__ == "__main__":
app.run()
通过
methods
限定访问方式, 接受参数形式为列表
# post
@app.route("/post_only", methods=["POST"])
def post_only():
return "post only page"
# get
@app.route("/get_only", methods=["GET"])
def get_only():
return "get only page"
# post or get
@app.route("/test", methods=["GET", "POST"])
def test():
return "post | get page"
@app.route("/hi1")
@app.route("/hi2")
def hi():
return "hi page"
访问这两个/hi1
,/hi2
路径显示的效果都是 hi page
使用
url_for()
的函数,可以通过 视图函数的名字 找到视图对应的url
路径 而redirect()
函数则是url
重定向,会再次发送一个新的请求。 从flask
库中导入这两个函数,一般这两个函数会一起使用。
from flask import Flask, url_for, redirect
app = Flask(__name__)
# app.route装饰器的作用是将路由映射到视图函数
@app.route("/hello")
def welcome():
return "hello flask"
@app.route("/")
def index():
return "index page"
@app.route("/login")
def login():
# url = "/hello"
# 使用url_for的函数,通过视图函数的名字找到视图对应的url路径
url = url_for("welcome")
print(url)
return redirect(url)
@app.route("/register")
def register():
url = "/"
# url = url_for("index")
return redirect(url)
if __name__ == "__main__":
app.run()
url_for('welcome') 等同于 /hello
url_for('index') 等同于 /
在测试功能前,首先在浏览器中,右击鼠标选择检查或 F12
打开浏览器调试工具。进入 NetWork
选项。
然后在网址栏上分别输入 http://127.0.0.1:5000/login
和http://127.0.0.1:5000/register
这里就展示访问 /login
的效果,可以发现直接跳转到了 /hello
。这就是 重定向,发送了两次请求。
然后再看看 PyCharm
运行 Flask
程序的信息。
127.0.0.1 - - [25/Apr/2021 15:09:34] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [25/Apr/2021 15:18:25] "GET /login HTTP/1.1" 302 -
/hello
127.0.0.1 - - [25/Apr/2021 15:18:25] "GET /hello HTTP/1.1" 200 -
127.0.0.1 - - [25/Apr/2021 15:29:05] "GET /register HTTP/1.1" 302 -
127.0.0.1 - - [25/Apr/2021 15:29:05] "GET / HTTP/1.1" 200 -
切记:url_for()
接收的是 视图函数的名称,返回的是对应的 url
路径,切勿把 url
路径传进去。
通过
app.url_map
可以查看所有路由信息
"""
Author: hui
Desc: { Flask 路由分发及静态资源访问 }
"""
from flask import Flask, url_for, redirect
app = Flask(__name__)
# app.route装饰器的作用是将路由映射到视图函数
@app.route("/hello")
def welcome():
return "hello flask"
@app.route("/")
def index():
# 通过url_map可以查看整个flask中的路由信息
print(app.url_map)
return "index page"
# 其他视图函数省略...
if __name__ == "__main__":
app.run()
访问首页打印如下结果
Map([<Rule '/post_only' (OPTIONS, POST) -> post_only>,
<Rule '/get_only' (OPTIONS, HEAD, GET) -> get_only>,
<Rule '/register' (OPTIONS, HEAD, GET) -> register>,
<Rule '/hello' (OPTIONS, HEAD, GET) -> welcome>,
<Rule '/login' (OPTIONS, HEAD, GET) -> login>,
<Rule '/test' (OPTIONS, HEAD, POST, GET) -> test>,
<Rule '/hi2' (OPTIONS, HEAD, GET) -> hi>,
<Rule '/hi1' (OPTIONS, HEAD, GET) -> hi>,
<Rule '/' (OPTIONS, HEAD, GET) -> index>])
有时我们需要将同一类URL映射到同一个视图函数处理 比如:使用同一个视图函数 来显示不同用户的个人信息。
"""
@Author: Hui
@Desc: { flask框架的转换器练习 }
"""
from flask import Flask
app = Flask(__name__)
# str转换器 不加转换器类型, 默认是普通字符串规则(除了/的字符)
@app.route('/user/<username>')
def user_str(username):
response = 'hello {}'.format(username)
return response
if __name__ == '__main__':
app.run()
注意:视图函数里接受的参数必须和 route
捕获尖括号 <>
里的参数一致。
# int转换器
@app.route('/user/<int:user_id>')
def user_int(user_id):
response = 'hello {}'.format(user_id)
return response
# path转换器
@app.route('/user/<path:user>')
def user_path(user):
response = 'hello {}'.format(user)
return response
自定义一个匹配正则
url
的转换器
首先导入 werkzeug.routing
中 BaseConverter
from werkzeug.routing import BaseConverter
然后自定义类继承 BaseConverter
from flask import Flask, url_for, redirect
from werkzeug.routing import BaseConverter
app = Flask(__name__)
# 自定义正则转换器
class RegexConverter(BaseConverter):
"""url正则匹配转换器"""
def __init__(self, url_map, regex):
super().__init__(url_map)
self.regex = regex
app.url_map.converters['re'] = RegexConverter
# 匹配手机号码的正则
MobileRegex = "'0?(13|14|15|17|18)[0-9]{9}'"
# 使用自定义的转换器
@app.route(f"/call/<re({MobileRegex}):tel>")
def call_tel(tel):
response = 'tel: {}'.format(tel)
return response
if __name__ == "__main__":
app.run()
to_python()
用于处理转换器提取出来的参数,可以进行修改。to_url()
使用 url_for() 时调用,其结果将作为url_for
的返回值
# 自定义正则转换器
class RegexConverter(BaseConverter):
"""url正则匹配转换器"""
def __init__(self, url_map, regex):
super().__init__(url_map)
self.regex = regex
def to_python(self, value):
print("to_python() called...")
print(f"value, {value}")
# value是在路径进行正则表达式匹配的时候提取的参数
# 留了一步处理提取出来参数
# 这里返回值是最终解析的结果
return 'tel update 110'
# return value
def to_url(self, value):
"""使用 url_for() 时调用"""
# 可以改变 url_for() 处理的结果
print("to_url() called...")
print(f"value, {value}")
return "15811111111"
# return value
app.url_map.converters['re'] = RegexConverter
# 匹配手机号码的正则
MobileRegex = "'0?(13|14|15|17|18)[0-9]{9}'"
# 使用自定义的转换器
@app.route(f"/call/<re({MobileRegex}):tel>")
def call_tel(tel):
response = 'tel: {}'.format(tel)
return response
@app.route("/call")
def call():
url = url_for('call_tel', tel='13577881658')
print(f'url -> {url}')
return redirect(url)
一般都无需重写,使用父类的就行。等有需求时在使用。
源代码已上传到 Gitee
HuiDBK/FlaskBasic - 码云 - 开源中国 (gitee.com),欢迎大家来访。