Flask路由
1.路由
1.1路由使用
1.1.1 @app.route()
# @app.route() 简单使用
# @app.route(url路由),这个调用路由要写在对应视图函数上访
@app.route("/")
def index():
return "HelloWord!"
# route()源码
def route(self, rule: str, **options: t.Any) -> t.Callable:
"""
# 装饰一个视图函数,用给定的URL注册它规则和选项。调用'add_url_rule'(其中包含更多内容关于实现的详细信息)
Decorate a view function to register it with the given URL
rule and options. Calls :meth:`add_url_rule`, which has more
details about the implemenstation.
# 如果'endpoint'参数没有传值,路由的端点名称默认为视图的名称函数
The endpoint name for the route defaults to the name of the view
function if the ``endpoint`` parameter isn't passed.
# 'methods'参数默认为["GET"],HEAD' 和'OPTIONS'会自动添加。如果想要其他请求就在methods=["GET","POST","XXX".....]
The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` and
``OPTIONS`` are added automatically.
# rule:url规则字符串
:param rule: The URL rule string.
# options:额外选项传给werkzeug.routing.Rule对象
:param options: Extra options passed to the
:class:`~werkzeug.routing.Rule` object.
"""
def decorator(f: t.Callable) -> t.Callable:
endpoint = options.pop("endpoint", None) # 从options字典中删除并获取endpoint的值,有endpoint就返回对应的值,没有就是接收None
self.add_url_rule(rule, endpoint, f, **options) # add_url_rule()才是route的核心
return f
return decorator # 调用route,返回内部函数地址,route是一个装饰器,它的主要作用在decorator函数内
1.1.2 app.add_url_rule()
# app.add_url_rule() 简单使用
# app.add_url_rule(URL路由,endpoint=None,view_func=视图函数名)
def index():
return "HelloWord!"
app.add_url_route("/",view_func=index) # 路由url:/ 与 视图函数index 绑定
# add_url_route 源码
def add_url_rule(
self,
rule: str,
endpoint: t.Optional[str] = None,
view_func: t.Optional[t.Callable] = None,
provide_automatic_options: t.Optional[bool] = None,
**options: t.Any,
) -> None:
# 如果没有传递'endpoint'参数,就把 视图函数的名称 传给 路由的端点名称。
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func) # type: ignore
options["endpoint"] = endpoint
methods = options.pop("methods", None)
# 1.判断method是否为None,如果为None,
# 2.使用反射getattr 去view_func去找methods属性值,如果view_func.metods存在 就把其值返回传给method,or后面就不用看,不存在返回的是None,就把or后面的("GET",)元组返回给method
if methods is None:
methods = getattr(view_func, "methods", None) or ("GET",)
# 判断 methods 是否为字符串,
if isinstance(methods, str):
raise TypeError(
"Allowed methods must be a list of strings, for"
' example: @app.route(..., methods=["POST"])'
)
# 把methods里面的请求方法变为大写,并且methods是集合自带去重
methods = {item.upper() for item in methods}
# Methods that should always be added (应该始终添加的方法)
# 如果view_func有required_methods属性,并把view_func.required_methods的值传回 并由set变成一个集合
required_methods = set(getattr(view_func, "required_methods", ()))
# 从Flask 0.8开始,view_func对象可以禁用和强制启用自动选项处理。
# 如果provide_automatic_options没有传参,就去view_func查找provide_automatic_options属性值,有值拿出并返回,没有返回None
if provide_automatic_options is None:
provide_automatic_options = getattr(
view_func, "provide_automatic_options", None
)
# 判断 从view_func中provide_automatic_options是否为None
if provide_automatic_options is None:
# 判断 methods集合中是否有"OPTIONS"请求方法,
#没有就把"OPTIONS"加入required_methods集合中,并把provide_automatic_options开启
#有"OPTIONS",就把provide_automatic_options关闭
if "OPTIONS" not in methods:
provide_automatic_options = True
required_methods.add("OPTIONS")
else:
provide_automatic_options = False
# 把请求方式综合到一块,集合method 和 集合required_methods 并集,并把结果集 赋值给methods
methods |= required_methods
# 创建rule并初始化url_rule_class对象
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options # type: ignore
# 把是上面实例化的路由对象 加载到 url_map(app的url路由映射里面)
self.url_map.add(rule)
if view_func is not None:
# 获取 视图函数的端点名
old_func = self.view_functions.get(endpoint)
# 视图函数的端点名有值(非None)且 端点名 和 视图函数名 不一样,就报错
if old_func is not None and old_func != view_func:
raise AssertionError(
"View function mapping is overwriting an existing"
f" endpoint function: {endpoint}"
)
# 视图函数的端点名为NOne,就把 视图函数名 传给 端点
self.view_functions[endpoint] = view_func
1.1.3总结
-
1.route()装饰器本质上还是 调用 add_url_rule()
""" @app.route("/") def index(): ... /\ /||\ || 上下两者等价 || \||/ \/ def index(): ... app.add_url_rule("/", view_func=index) """
-
2.如果rule规则参与路由的端点名称(某个视图函数必须被某个端点相关联("endpoint"装饰器装饰)),'view_func'不一定需要传参
app.add_url_rule("/", endpoint="index") @app.endpoint("index") def index(): ...
-
3.路由视图函数上加自写装饰器,需要在装饰器中调用@wraps(接收的外部函数名的形参名)
在flask中路由,url与视图函数的映射,实际是就是通过 endpoint 关联起来的。 如果'endpoint'参数没有传值,路由的端点名称默认为视图的名称函数(内部操作最终默认即为view_func.__name__),如果传参,还要保证传的参数名字 和 传的view_func函数名值一样。通俗讲就是 不管怎样 endpoint 和 view_func.__name__名字一样。 在项目后期,如果给视图函数加上自写的装饰器,有可能会导致该视图函数view_func.__name__值发生变化,从而导致视图函数重复 # 例如: #1.不加装饰器 @app.route("/") def home(): return "你好" print(home.__name__) # home.__name__的值为 home # 2.加上装饰器 def login_decorator(func): def wrapper(*args,**kwargs): .... # 这里写验证是否已登录相关代码 return fun(*args,**kwargs) return wrapper @login_decorator @app.route("/") def home(): return "你好" print(home.__name__) # home.__name__的值为 wrapper # 3.加上装饰器里面写上 wraps装饰器 def login_decorator(func): @wraps(func) # 本质就是wrapper.__name__=func.__name__ def wrapper(*args,**kwargs): .... # 这里写验证是否已登录相关代码 return fun(*args,**kwargs) # wrapper.__name__=func.__name__ return wrapper @login_decorator @app.route("/") def home(): return "你好" print(home.__name__) # home.__name__的值为 home
1.2查看路由信息
1.2.1 在终端以命令行的方式:
①首先需要通过加载FLASK_APP环境变量告诉你的终端要查看谁的应用程序路由(把你要运行的app实例文件名传给FLASK_APP,详情参考终端启动加载FLASK_APP环境变量)
# 在linux终端
export FLASK_APP=hello
# 在win的cmd终端窗口
set FLASK_APP=hello
# 在win的Powershell窗口(在pycharm中的Terminal窗口,pycharm版本不是很老的话,一般默认都是Powershell)
$env:FLASK_APP = "hello"
# 参数说明:
FLASK_APP=xxxx 亦或 FLASK_APP = "xxxx" 其中xxxx表示APP实例文件名 ,上面写的hello就是创建APP实例文件名
# 上面中hello实例文件 创建详情 点击上面 详情参考
②命令行输入:flask routes,但是flask routes 获取的路由信息不是很全
# 输入:flask routes
# 得到类似下面结果:
(端点) (请求方法) (路由规则)
Endpoint Methods Rule
----------- ------- -----------------------
hello_world GET /
static GET /static/<path:filename>
endpoint:端点,视图函数名的字符串形式;
methods:请求方法;
rule:路径规则;
static是Flask框架帮我们默认创建的静态路由,方便静态文件的访问
1.2.2 在程序中获取
①在应用中的url_map属性中保存着整个Flask应用的路由映射信息,可以通过读取这个属性获取全部路由信息
# 1.在app实例文件里面写上如下:
print(app.url_map)
# 2.运行该app实例文件,得到结果如下:
Map([<Rule '/' (HEAD, GET, OPTIONS) -> hello_world>,
<Rule '/static/<filename>' (HEAD, GET, OPTIONS) -> static>])
map:表示路由映射,容器列表;
python中<>存储的信息,一般表示对象;
Rule:路径规则,存储了url的路径名、http请求方法、端点(视图函数名)
1.3 通过ipython和应用程序进行交互(这里通过pycharm里面的Python Console窗口进行交互,如下图所示),在app.app_context()设置一个应用程序上下文current_app.url_map来获取路由信息。
# 输入以下命令:
from hello import app # hello是 实例app文件,从hello导出app实例对象
with app.app_context(): # 应用上下文配置
from flask import current_app
print(current_app.url_map) # 查看路由信息
# 得到结果如下:
Map([<Rule '/' (HEAD, GET, OPTIONS) -> hello_world>,
<Rule '/static/<filename>' (HEAD, GET, OPTIONS) -> static>])
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)