【python】Flask之路由
一、关于路由
所谓路由,就是处理请求URL和函数之间关系的程序
根据例子看源码
from flask import Flaskapp = Flask(__name__)@app.route('/')
def index():return 'hello world!'if __name__ == '__main__':app.run()
Flask中对URL规则进行统一管理的,创建URL规则有两种方式:
使用@app.route修饰器
传入URL规则作为参数,将函数绑定到URL,这个过程便将一个函数注册为路由,这个函数则被称为视图函数使用app.add_url_rule()
二、注册路由
定位到@app.route修饰器,看看route是什么
def route(self, rule, **options):def decorator(f):endpoint = options.pop("endpoint", None)self.add_url_rule(rule, endpoint, f, **options)return freturn decorator
很明显,这是一个装饰器,route()有两个参数,rule表示url规则
该函数对参数进行处理之后,调用方法add_url_role(),这里也就验证了两种注册路由的方法等价
继续定位add_url_rule这个方法:
@setupmethoddef add_url_rule(self,rule,endpoint=None,view_func=None,provide_automatic_options=None,**options):....
这个方法传入的参数有这些:
- rule: url规则
- endpoint: 要注册规则的endpoint,默认是视图函数的名
- view_func: 视图函数
- provide_automatic_options: 请求方法是否添加OPTIONS方法的一个标志
- options: 关于请求处理的一些方法等
三、endpoint
着重介绍下endpoint,中文意思是端点
flask内部先把URL地址映射到端点(endpoint)上,然后再映射到视图函数(view_func)
看一个例子:
from flask import Flaskapp = Flask(__name__)# 这里我们加个参数endpoint
@app.route('/', endpoint="say_hello")
def index():return 'hello world!'if __name__ == '__main__':app.run()
继续看源码add_url_rule:
...if endpoint is None:endpoint = _endpoint_from_view_func(view_func)options["endpoint"] = endpointmethods = options.pop("methods", None)
这句话的意思是说如果endpoint没有, 就调用_endpoint_from_view_func方法,看一下_endpoint_from_view_func方法知道它其实就是返回view_func的名称
def _endpoint_from_view_func(view_func):"""Internal helper that returns the default endpoint for a givenfunction. This always is the function name."""assert view_func is not None, "expected view func if endpoint is not provided."return view_func.__name__
所以通常来说,endpoint 不写,默认值就是和view_func同一个名称
作用
那么它的作用是什么呢?
端点通常用作反向查询URL地址(viewfunction–>endpoint–>URL)
例如,在flask中有个视图,想把它关联到另一个视图上(或从站点的一处连接到另一处), 可以直接使用URL_for()
看一个例子:
from flask import Flask, url_for, redirectapp = Flask(__name__)@app.route('/')
def index():# url_for第一个参数就是endpointlogin_url = url_for('login', name="tony")print(login_url) # 打印 /login/tonyreturn redirect(login_url) # 自动跳转到另一个URL所在的地址return '这是首页'@app.route('/login/<name>')
def login(name):print("name=", name)return '这是登录页面'if __name__ == '__main__':app.run() # 默认端口5000
四、url_for()与重定向
url(路由)和函数视图的映射关系,即通过对应的url可以返回对应的视图函数。当然通过视图函数也能找到对应的url路径,这可以通过url_for来完成
4.1 url_for
在浏览网页的时候都会有跳转,假设写跳转时用url路径,当整个网站路径需要修改时需要更改这些代码,如果使用的是url_for修改量就很少(通常视图函数是不修改)
看看url_for的使用:
@app.route('/post/list/<page>/')
def my_list(page):return 'my list'print(url_for('my_list',page=1,count=2))
# 构建出来的url:/my_list/1/?count=2
4.2 重定向
重定向分为永久性重定向和暂时性重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此应重定向到登录页面
具体操作如下:
from flask import Flask,request,redirect,url_forapp = Flask(__name__)@app.route('/login/')
def login():return '这是登录页面'@app.route('/profile/')
def profile():if request.args.get('name'):return '个人中心页面'else:# redirect 重定向return redirect(url_for('login'))
五、路由匹配
在应用初始化的过程中,会注册所有的路由规则,可以调用app.url_map
查看,当服务收到URL请求时,就需要进行路由匹配,以找到对应的视图函数,对应的流程和原理是什么呢?
当用户请求进入Flask应用时,首先会调用Flask里面的__call__方法,这个方法会调用Flask类的wsgi_app方法:
class Flask(_PackageBoundObject):
....def __call__(self, environ, start_response):"""The WSGI server calls the Flask application object as theWSGI application. This calls :meth:`wsgi_app` which can bewrapped to applying middleware."""return self.wsgi_app(environ, start_response)
定位wsgi_app方法:
def wsgi_app(self, environ, start_response):ctx = self.request_context(environ)error = Nonetry:try:ctx.push()response = self.full_dispatch_request()except Exception as e:error = eresponse = self.handle_exception(e)except: # noqa: B001error = sys.exc_info()[1]raisereturn response(environ, start_response)finally:if self.should_ignore_error(error):error = Nonectx.auto_pop(error)
该函数的处理过程包括:
- 创建RequestContext对象,在对象初始化的过程中调用app.create_url_adapter()方法,将请求参数environ传给Map对象创建MapAdapter对象,保存在url_adapter字段中
- 将RequestContext对象推入_request_ctx_stack栈中
- 通过RequestContext的match_request方法,调用MapAdapter对象的match方法找到匹配的Rule并解析出参数,保存在request的url_rule和view_args字段中
- 调用full_dispatch_request()
接下来看下full_dispatch_request方法:
def full_dispatch_request(self):self.try_trigger_before_first_request_functions()try:request_started.send(self)rv = self.preprocess_request()if rv is None:rv = self.dispatch_request()except Exception as e:rv = self.handle_user_exception(e)return self.finalize_request(rv)
看到这里调用了self.dispatch_request()方法:
def dispatch_request(self):req = _request_ctx_stack.top.requestif req.routing_exception is not None:self.raise_routing_exception(req)rule = req.url_rule# if we provide automatic options for this URL and the# request came with the OPTIONS method, reply automaticallyif (getattr(rule, "provide_automatic_options", False)and req.method == "OPTIONS"):return self.make_default_options_response()# otherwise dispatch to the handler for that endpointreturn self.view_functions[rule.endpoint](**req.view_args)
处理的过程是:
- 获取请求对象的request,找到对应的endpoint
- 从view_functions中找到对应的视图函数,传递请求参数
- 视图函数处理内部逻辑并返回,完成一次请求分发
六、动态路由
6.1 动态路由传参
http://127.0.0.1:5000/student_list/2/
在path中有可变的部分,达到了传参的目的,称之为动态路由传参
@app.route('/student_list/<student_id>/')
def student_list(student_id):return '学生{}号的信息'.format(student_id)
6.2 动态路由的过滤
可以对参数限定数据类型,比如限定为student_id必须为整数类型
http://127.0.0.1:5000/student_list/2/
@app.route('/student_list/<int:student_id>/')
def article_detail(student_id):print(student_id, type(student_id))return '学生{}号的信息'.format(student_id)
主要有这几种类型过滤:
string
: 默认的数据类型,接收没有任何斜杠" /"的字符串int
: 整型float
: 浮点型path
: 和string类型相似,但是接受斜杠,如:可以接受参数/aa/bb/cc/多条放在一起uuid
: 只接受uuid格式的字符串字符串
提示:uuid为全宇宙唯一的串
七、视图函数的URL路由设置
7.1 app.url_map查看所有路由
Flask的路由可以通过视图函数的修饰器@app.route()来配置访问url
在Django中可以在urls.py中查看所有视图的url信息,那么Flask如何查看所有视图url的信息呢?
可以看到日志中打印出了url的信息
7.2 使用methods设置视图请求的方式
在Flask的视图配置了url之后,默认是只支持GET请求的。如果需要处理POST请求,则需要使用methods参数设置一下
# 通过methods设置GET\POST请求
@app.route('/post_only', methods=["POST"])
def post_only():return "post only page"
在浏览器访问: http://127.0.0.1:5000/post_only
可以看到不允许GET请求
7.3 同一路由装饰多个视图函数
在同一个url路由的请求下,可以会有GET\POST\DELETE\PUT等多个不同的业务处理
那么就需要使用不同的视图函数来区分处理
@app.route('/hello', methods=["GET"])
def hello_get():return "hello_get"@app.route('/hello', methods=["POST"])
def hello_post():return "hello_post"
- 测试访问GET请求 http://127.0.0.1:5000/hello
- 测试访问POST请求 http://127.0.0.1:5000/hello
从结果来看,同一个url下,根据配置不同的method,则可以设置到不同的视图函数进行业务处理
7.4 同一视图多个路由装饰器
一个视图如何定义多个url进行访问?
在Django中只要在urls.py中设置多行url定义即可,而在Flask中只需要使用多个路由修饰器进行定义
# 一个视图设置多个URL
@app.route('/diff_url1')
@app.route('/diff_url2')
def diff_url():return "diff url"
- 访问第一个url地址 http://127.0.0.1:5000/diff_url1
- 访问第二个url地址 http://127.0.0.1:5000/diff_url2
7.5 使用 url_for 进行反解析
在Flask中则可以使用url_for来进行反向解析,而Flask的视图函数不需要设置name,而是直接使用视图函数的函数名即可
from flask import redirect, url_for@app.route('/hello', methods=["GET"])
def hello_get():return "hello_get"# 使用url_for进行反向解析
@app.route('/url_for_test')
def url_for_test():return redirect(url_for('hello_get'))
测试访问 http://127.0.0.1:5000/url_for_test
可以看到页面自动跳转至hello_get的视图函数中
【python】Flask之路由相关推荐
- Python Flask 中的路由
Python Flask 中的路由 在 Web 应用中,接口一般都是遵守 RESTful API 设计风格的,这种风格很优雅,而且对用户来说非常易于理解. RESTful API 参考:https:/ ...
- Python Flask 路由配置
有关更多的Python 开发内容,可访问:< Python Flask开发指南> Flask中通过使用route装饰器实现路由访问功能,其路由匹配URL规则基于Werkzeug的路由模块. ...
- python flask 路由_python框架之Flask(2)-路由和视图Session
路由和视图 这一波主要是通过看源码加深对 Flask 中路由和视图的了解,可以先回顾一下装饰器的知识:[装饰器函数与进阶] 路由设置的两种方式 #示例代码 from flask importFlask ...
- python flask源码解析_用尽洪荒之力学习Flask源码
[TOC] 一直想做源码阅读这件事,总感觉难度太高时间太少,可望不可见.最近正好时间充裕,决定试试做一下,并记录一下学习心得. 首先说明一下,本文研究的Flask版本是0.12. 首先做个小示例,在p ...
- python Flask框架如何请求及返回数据——flask详细教程
python Flask框架如何请求及返回数据--flask详细教程 文章目录: 1 Flask介绍 1.1 Flask简单介绍 1.2 Flask相关资料信息 2 Flask快速入门 2.1 Fla ...
- python flask安装_python flask安装和命令详解
Flask Web开发实战学习笔记 Flask简介 Flask是使用Python编写的Web微框架.Web框架可以让我们不用关 心底层的请求响应处理,更方便高效地编写Web程序.因为Flask核心简 ...
- python flask快速入门与进阶 百度云_Python Flask快速入门与进阶
课程目录 1-1 Python Flask快速入门与进阶.mp4 2-1 windows环境安装开发环境 (上).mp4 2-2 windows环境安装开发环境 (下).mp4 2-3 配置开发环境. ...
- python flask框架剖析_python flask框架实现传数据到js的方法分析
本文实例讲述了python flask框架实现传数据到js的方法.分享给大家供大家参考,具体如下: 首先要清楚后台和前端交互所采用的数据格式. 一般选JSON,因为和js完美贴合. 后台返回的数据进行 ...
- python flask框架教程_Flask框架从入门到实战
Flask简介: Flask是一个使用 Python 编写的轻量级 Web 应用框架,基于 WerkzeugWSGI工具箱和 Jinja2模板引擎.使用 BSD 授权. Flask也被称为 " ...
最新文章
- 腾讯云区块链,打造基础设施之上的生态系统
- ElasticSearch bool过滤查询
- bat批处理for /f命令
- Dos批处理编程常用命令
- 缠论k线合并处理python实现_缠论期货:道琼斯工业指数缠论分解体系5F趋势背驰,3买能否构筑成功?...
- 心路历程(四)-我的2015
- lua操作redis
- C语言成语设计第一次作业
- 2022版保姆级Idea调试jdk源码
- 利用Hilbert变换进行相位调制信号的解调
- CF 346 B vectorpair s[100]
- 模糊综合评价在实际问题中的应用(案例)
- 2020-09-07关皓
- 移动端开发(学好移动端这一篇就够啦)
- USB驱动分析(三)
- Walk Through the Fire,Is there a way out
- 项目管理(四):项目整合管理
- 网络攻击中主动攻击和被动攻击分别指什么?
- 常见的网络问题-初级
- Mac 抓包工具 Charles瓷器瓶破解版安装和破解教程
热门文章
- VLClclc Plugin Object的方法
- iOS 相册,图片裁剪工具(附demo)
- Java Web实现用户注册页面的提交
- 中国76个量子比特计算机,再破纪录!中国科学家实现18个量子比特纠缠 为量子计算机奠基...
- Cosmos IBC
- mysql印度时区_一次 JDBC 与 MySQL 因 “CST” 时区协商误解导致时间差了 14 或 13 小时的排错经历...
- 计算机毕业设计Python+uniapp“宠到家”宠物领养小程序(小程序+源码+LW)
- 分布式和集群的概念区别
- Linux学习笔记(22.2)——基于IIC + Regmap + IIO的AP3216C的设备驱动
- Scala中List的步长by