路由的基本使用
1. 添加路由的两种方式
- 方式一 -> 通过装饰器添加路由
# app.py
from flask import Flask
app = Flask(__name__)
# 路由的配置
@app.route('/login') # 路由地址
def login(): # 视图函数
return 'login'
@app.route('/')
def index():
return 'index'
if __name__ == '__main__':
app.run() # 启动 Flask
- 方式二 -> 通过 app.add_url_rule() 方法添加路由
- 其实 @app.route() 装饰器本质上也是使用了 .add_url_rule() 方法添加路由的
# app.py
from flask import Flask
app = Flask(__name__)
def login():
return 'login'
app.add_url_rule(rule='/login', endpoint=None, view_func=login) # 添加路由 -> rule: 路由地址, endpoint: 路由别名, view_func: 视图函数
def index():
return 'index'
app.add_url_rule(rule='/index', endpoint=None, view_func=index) # 添加路由 -> rule: 路由地址, endpoint: 路由别名, view_func: 视图函数
if __name__ == '__main__':
app.run() # 启动 Flask
- 使用方式二仿照Django的路由写法
# app.py
from flask import Flask
app = Flask(__name__)
def login():
return 'login'
def index():
return 'index'
urls = [
('/login', None, login),
('/index', None, index),
]
for url in urls:
app.add_url_rule(rule=url[0], endpoint=url[1], view_func=url[2]) # 添加路由 -> rule: 路由地址, endpoint: 路由别名, view_func: 视图函数
if __name__ == '__main__':
app.run()
@app.route 和 app.add_url_rule 的路由参数
参数 | 说明 |
rule | 路由地址(即: url规则) |
view_func | 视图函数名 |
methods | 设置允许xxx请求访问当前路由,默认 GET 请求 |
defaults | 默认值,当URL中无参数,函数需要参数时,使用defaults={'key': 'value'}为函数提供参数 |
endpoint | 路由别名,相当于Django路由中的name,用于反向生成 url |
strict_slashes | 对URL最后的 / 符号是否严格要求 |
redirect_to | 重定向到指定地址 |
subdomain | 子域名访问 |
1. rule
- 路由地址
- @app.route
# app.py
from flask import Flask
app = Flask(__name__)
@app.route(rule='/login')
def login():
return 'login'
if __name__ == '__main__':
app.run()
- app.add_url_rule
# app.py
from flask import Flask
app = Flask(__name__)
def login():
return 'login'
app.add_url_rule(rule='/login', view_func=login)
if __name__ == '__main__':
app.run()
2. view_func
- 视图函数名
- app.add_url_rule
# app.py
from flask import Flask
app = Flask(__name__)
def login():
return 'login'
app.add_url_rule(rule='/login', view_func=login)
if __name__ == '__main__':
app.run()
3. methods
- 设置允许xxx请求访问当前路由,默认 GET 请求
- @app.route
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/login', methods=['GET', 'POST'])
def login():
return 'login'
if __name__ == '__main__':
app.run()
- app.add_url_rule
# app.py
from flask import Flask
app = Flask(__name__)
def login():
return 'login'
app.add_url_rule(rule='/login', view_func=login, methods=['GET', 'POST'])
if __name__ == '__main__':
app.run()
4. defaults
- 默认值,当URL中无参数,函数需要参数时,使用defaults={'key': 'value'}为函数提供参数
- @app.route
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/login', defaults={'name': 'Kevin', 'password': 123})
def login(name, password):
print(name, password) # Kevin 123
return 'login'
if __name__ == '__main__':
app.run()
- app.add_url_rule
# app.py
from flask import Flask
app = Flask(__name__)
def login(name, password):
print(name, password) # Kevin 123
return 'login'
app.add_url_rule(rule='/login', view_func=login, defaults={'name': 'Kevin', 'password': 123})
if __name__ == '__main__':
app.run()
5. endpoint
- 路由别名,相当于Django路由中的name,用于反向生成 url
- endpoint 默认值: 视图函数
- @app.route
# app.py
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/login', endpoint='login_url')
def login():
print(url_for('login_url')) # /login
return 'login'
if __name__ == '__main__':
app.run()
- app.add_url_rule
# app.py
from flask import Flask, url_for
app = Flask(__name__)
def login():
print(url_for('login_url')) # /login
return 'login'
app.add_url_rule(rule='/login', view_func=login, endpoint='login_url')
if __name__ == '__main__':
app.run()
6. strict_slashes
- 对URL最后的 / 符号是否严格要求
- 默认值: None
- 值:
- None: 开启严格模式 -> 当 url 后面没有 / 时,不能加 / 进行访问
- True: 开启严格模式 -> 当 url 后面没有 / 时,不能加 / 进行访问
- False: 关闭严格模式 -> 当 url 后面没有 / 时,可以加 / 进行访问
- @app.route
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/login', strict_slashes=False)
def login():
return 'login'
if __name__ == '__main__':
app.run()
- app.add_url_rule
# app.py
from flask import Flask
app = Flask(__name__)
def login():
return 'login'
app.add_url_rule(rule='/login', view_func=login, strict_slashes=False)
if __name__ == '__main__':
app.run()
7. redirect_to
- 重定向到指定地址
- 使用场景: 当有了新系统或网站,旧的系统或网站不能立刻停掉,当访问旧系统或网站的时候重定向到新的系统或网站
- @app.route
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/index', redirect_to='/new_index')
def index():
return 'index'
@app.route('/new_index')
def new_index():
return 'new_index'
if __name__ == '__main__':
app.run()
- app.add_url_rule
# app.py
from flask import Flask
app = Flask(__name__)
def index():
return 'index'
app.add_url_rule(rule='/index', view_func=index, redirect_to='/new_index')
@app.route('/new_index')
def new_index():
return 'new_index'
app.add_url_rule(rule='/index', view_func=new_index)
if __name__ == '__main__':
app.run()
8. subdomain
- 子域名访问
- 添加子域名


- 刷新子域名
- ipconfig /flushdns

- 编写子域名访问
- @app.route
# app.py
from flask import Flask
app = Flask(__name__)
app.config['SERVER_NAME'] = 'kevin.com:5000' # 配置域名 + 端口,一定要添加该配置,否则无法生效
# http://admin.kevin.com:5000/
@app.route('/', subdomain='admin') # 设置子域名
def admin_index():
return 'admin_index'
# http://web.kevin.com:5000/
@app.route('/', subdomain='web') # 设置子域名
def web_index():
return 'web_index'
# http://任意前缀.kevin.com:5000/dynamic
@app.route('/dynamic', subdomain='<prefix_name>') # <prefix_name> 表示匹配任意的子域名前缀
def prefix_index(prefix_name):
return prefix_name + '_index'
if __name__ == '__main__':
app.run()
- app.add_url_rule
# app.py
from flask import Flask
app = Flask(__name__)
app.config['SERVER_NAME'] = 'kevin.com:5000' # 配置域名 + 端口,一定要添加该配置,否则无法生效
def admin_index():
return 'admin_index'
# http://admin.kevin.com:5000/
app.add_url_rule(rule='/', view_func=admin_index, subdomain='admin') # 设置子域名
def web_index():
return 'web_index'
# http://web.kevin.com:5000/
app.add_url_rule(rule='/', view_func=web_index, subdomain='web') # 设置子域名
def prefix_index(prefix_name):
return prefix_name + '_index'
# http://任意前缀.kevin.com:5000/dynamic
app.add_url_rule(rule='/dynamic', view_func=prefix_index, subdomain='<prefix_name>') # <prefix_name> 表示匹配任意的子域名前缀
if __name__ == '__main__':
app.run()
带参数的URL
注意: 如果使用了带参数的URL,那么视图函数一定要接收这个参数,不然就会报错
1. 语法
# 没有指定数据类型的参数,默认该参数为 string 类型
@app.route('/user/<参数名>')
# 指定数据类型的参数
@app.route('/user/<数据类型:参数名>')
2. 常用的数据类型
@app.route('/user/<username>') # 如果不指定数据类型,默认使用string类型
@app.route('/user/<string:username>') # string -> 字符串
@app.route('/post/<int:post_id>') # int -> 整形
@app.route('/post/<float:post_id>') # float -> 浮点型
@app.route('/post/<path:url>') # 路径类型
3. 路由系统的数据类型与转换器的对应关系
# UnicodeConverter 等,这些都是转换器
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
4. 使用例子一
- 接收一个参数
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/news/<int:nid>')
def news(nid): # 一定要接收URL中的参数否则会报错
print(nid) # 10
return 'news'
if __name__ == '__main__':
app.run()
5. 使用例子二
- 接收多个参数
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/news/<int:nid>/<int:uid>')
def news(nid, uid): # 一定要接收URL中的参数否则会报错
print(nid) # 10
print(uid) # 5
return 'news'
if __name__ == '__main__':
app.run()
自定义正则路由匹配
执行流程:
- 用户发送请求
- Flask内部进行正则匹配
- 匹配成功后调用 to_python(正则匹配的结果) 方法
- 将 to_python() 方法的返回值交给视图函数的参数
- 使用url_for反向生成URL时会触发 to_url() 方法,帮助我们反向生成url
# app.py
from flask import Flask, url_for
from werkzeug.routing import BaseConverter
app = Flask(import_name=__name__)
# 步骤一: 定制转换器
class RegexConverter(BaseConverter):
"""
自定义正则路由匹配
"""
def __init__(self, map, regex):
super(RegexConverter, self).__init__(map)
self.regex = regex # '\d+' -> 接收你所传递的正则表达式,Flask会自动进行正则匹配
def to_python(self, value):
"""
路由匹配成功后执行该方法,将匹配到的值返回给视图函数
:param value: 匹配成功的值
"""
return int(value)
def to_url(self, value):
"""
使用url_for反向生成URL时执行该方法,url_for所传递的参数经过该方法进行处理,返回的值是用于生成URL中的参数
:param value: url_for 传递过来的参数
"""
val = super(RegexConverter, self).to_url(value) # 888
return val
# 步骤二: 将转换器添加到Flask中
app.url_map.converters['reg'] = RegexConverter
# 步骤三: 使用自定义正则
@app.route('/index/<reg("\d+"):nid>') # reg("\d+") 实例化对象,执行 RegexConverter 构造方法
def index(nid):
print(nid) # url匹配到的参数
url = url_for('index', nid='888') # 反向生成url,触发 to_url 方法
print(url) # /index/888
return 'Index'
if __name__ == '__main__':
app.run()
命名URL(URL反向查询)
命名URL(URL反向解析)通俗理解: 通过url别名反向查找出实际的URL
命名URL(URL反向解析)的好处: 当我们修改了路由中的url路径也不会影响到视图函数或模板中使用了该路径的地方,因为是通过url别名反向查找出实际的URL
在以后日常开发中都要使用 命名URL(URL反向解析)
1. 命名URL
- endpoint 相当于 Django 路由中的 name
- endpoint 的默认值: 它所绑定的视图函数名(即: 如果 endpoint 没有指定,那么 endpoint 会默认指向它所绑定的视图函数名)
- endpoint 的值不能重复
- 语法: endpoint='url别名'
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/index/', endpoint='index_url')
def index():
return 'index'
if __name__ == '__main__':
app.run()
2. URL反向查询(URL不带参数)
- 通过 url_for 反向查询出url别名所指定的url路径
- 语法: url_for='url别名'
# app.py
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/index/', endpoint='index_url')
def index():
this_url = url_for('index_url') # 通过url别名反向查询出它的url
print(this_url) # /index/
return 'index'
if __name__ == '__main__':
app.run()
3. URL反向查询(带参数的URL)
# app.py
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/index/<int:uid>/<int:nid>')
def index(uid, nid):
this_url = url_for('index', uid=1, nid=5) # 通过url别名反向查询出它的url
print(this_url) # /index/1/5
return 'index'
if __name__ == '__main__':
app.run()
4. URL反向查询(没有指定endpoint)
- 如果没有指定 endpoint 那么默认使用视图函数名进行反向查询,因为 endpoint 默认指向它所绑定的视图函数名
# app.py
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/index/')
def index():
this_url = url_for('index') # 如果没有指定 endpoint 那么默认使用视图函数名进行反向查询,因为 endpoint 默认指向它所绑定的视图函数名
print(this_url) # /index/
return 'index'
if __name__ == '__main__':
app.run()