Flask对请求的处理的原理
- flask处理请求过程
- 所有Flask程序必须有一个应用程序实例,相当于django的project。
- 当客户端想要获取资源时,一般会通过浏览器发起HTTP请求。
- 此时,Web服务器使用WSGI(Web Server Gateway Interface)协议,把来自客户端的所有请求都交给Flask程序实例,程序实例使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)。
- 根据每个URL请求,找到具体的视图函数并进行调用。
- Flask实现路由分发的方式
- 在Flask程序中,路由的实现一般是通过程序实例的装饰器实现。
- Flask视图函数返回的内容
- 字符串内容:将视图函数的返回值作为响应的内容,返回给客户端(浏览器)
- HTML模版内容:获取到数据后,把数据传入HTML模板文件中,模板引擎负责渲染HTTP响应数据,然后返回响应数据给客户端(浏览器)
Flask应用程序(示例)
- 实现流程
- 1.创建一个项目文件夹
- 2.创建hello.py的文件
- 3.导入flask类
- 4.创建Flask实例,Flask类接收参数name,它会指向程序所在的模块
- 5.通过装饰器的方式,将路由映射到视图函数index
- 6.启动web服务器,Flask应用程序实例的run方法启动WEB服务器,默认5000端口
- 代码
flask应用实例的使用和基本配置
- flask实例初始化
- from flask import Flask
- app = Flask(import_name, static_url_path, static_folder, template_folder)
- import_name: 模块名,一般写__name__
- static_url_path: 静态文件访问前缀
- static_folder: 默认‘static’
- template_folder: 默认‘templates’
- 配置参数
- 第一种方法:通过类来配置
- 先定义配置相关类
- class Config(object):
- DEBUG = True
- 在通过类来配置flask实例
- app.config.from_object(Config)
- 第二种方法:通过文件的方式来配置
- 创建配置文件,并编辑相关配置
- DEBUG = True
- 通过文件来配置flask实例
- app.config.from_pyfile(“yourconfig.cfg”)
- 第三种方法: 单条配置
- app.config['DEBUG'] = True
- 第四种方法: 在启动应用实例的时候直接添加配置
- app.run(debug = True)
- 运行flask引用程序
- 运行方法
- app.run()
- 指定参数运行
- app.run(host="0.0.0.0", port=5000, debug = True)
- 可以通过传入参数实现指定端口,设置主机,添加配置的效果
- host为0.0.0.0的时候,本地和局域网内都可以访问
- 读取配置参数
- app.config.get() 读取配置信息
- current_app.config.get() 在视图中读取配置信息
- lask应用实例的其他属性\方法
- app.url_map 获取当前app所有的路由和视图函数的映射,默认包含了静态文件的映射关系
- app.url_map.converts 返回所有路由转换器
路由介绍和配置
- Flask装饰器路由的实现:
- Flask实现路由的核心:Werkzeug-实现路由、调试和Web服务器网关接口。
- Werkzeug是一个遵循WSGI协议的python函数库。其内部实现了很多Web框架底层的东西,比如request和response对象;与WSGI规范的兼容;支持Unicode;支持基本的会话管理和签名Cookie;集成URL请求路由等。
- Werkzeug库的routing模块负责实现URL解析。不同的URL对应不同的视图函数,routing模块会对请求信息的URL进行解析,匹配到URL对应的视图函数,以此生成一个响应信息。
- routing模块内部有:
- Rule类(用来构造不同的路由URL对象),存储路由和视图的映射,
- Map类(存储所有的URL规则),将多个Rule存入map中,
- BaseConverter的子类(存储的是参数匹配规则),存储所有的url匹配规则
- MapAdapter类(负责具体URL匹配的工作),拿到url与Rule进行匹配
- 路由匹配视图函数的规则
- 路由在匹配过程中,至上而下依次匹配;
- 当匹配到视图函数的时候便会将请求信息传递给对应视图函数,不会再向下匹配;
- 所以当同一个路由匹配多个视图函数的时候,只会去执行第一个视图函数的业务代码;
- 限定请求方式
- 配置方法
- 使用 methods 参数指定可接受的请求方式,可以是多种,默认是GET
- Flask会默认就含有DEAD、OPTION请求方式
- 代码示例
- 指定路由参数
- 配置方法
- 将参数部分用尖括号<>括起来,括号中的部分代表是url中的参数部分,默认是字符串类型
- 指定的参数会传递给视图函数
- 代码示例
- 路由转换器
- 路由转换器的作用
- 可以限定路由参数的内容
- 可以通过转化器方法对匹配到的路由参数做相应的处理
- 使用路由转换器
- 通过在指定参数的时候调用路由转换器,对参数做限制和处理等
- # re:路由转换器名称;括号中的内容是创建转换器实例传递的参数,参数可以传递多个,用" , "隔开
- @app.route(/user/<re("[0-9]{4}"):user_id>)
- def index(user_id):
- .......
- Flask自带的路由转换器
- 查看自带路由转换器方法
- app.url_map.converts
- 自带的路由转换器
- default UnicodeConverter
- 可以匹配Unicode类型的数据
- string UnicodeConverter
- 可以匹配Unicode类型的字符串
- any AnyConverter
- 可以匹配固定的几个设定的参数
- path PathConverter
- 可以匹配带"/"路径符号的参数
- int IntegerConverter
- 可以匹配整数类型的字符串
- float FloatConverter
- 可以匹配浮点类型的字符串
- uuid UUIDConverter
- 可以匹配一个32位的唯一通用识别码(uuid风格的)字符串
- 输出一个唯一的uuid类型的数据的方法
- import uuid
- 1.uuid.uuid1()
- 2.uuid.uuid4()
- uuid.uuid1()
- 自定义路由转换器(正则路由)
- 导入转换器的父类
- from werkzeug.routing import BaseConverter
- 定义正则路由转换器
- 第一种方法
- 该方法只能用父类的regex属性定义一种匹配规则,适用性不强
- 第二种方法
- 该方法可以实现通过传递进来的匹配规则来进行匹配
- 将自定义路由转换器添加到默认的转换器列表中,并指定转换器的名称
- app.url_map.converters['re'] = RegexConverter
- 路由转换器的其他方法(在自定义路由转换器中使用)
- to_python( ) 方法
- 功能
- 在参数匹配完成之后再传入到视图函数之前调用,并将函数处理后的参数内容传入视图函数
- 代码示例:
- def to_python(self, value):
- v = int(value) 将参数转化为整数
- return v 将参数传递给视图函数
- to_url():
- 功能
- 此方法会在进行路由跳转时在匹配跳转的路由函数之前调用,可使用此方法对url_for传入的内容进行处理
- 代码示例
- def to_url(self, value):
- v = int(value)
- return '%d' % v
视图函数的配置
- 上下文
- Flask上下文的概念
- 相当于一个容器,保存了Flask程序运行过程中的一些信息。
- Flask中有两种上下文,请求上下文和应用上下文。
- 应用上下文
- 概念
- 它的字面意思是应用上下文,但它不是一直存在的,它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。
- 只有在程序完全运行起来之后才能调用
- 应用上下文包含
- current_app
- 应用程序上下文,用于存储应用程序中的变量,可以通过current_app.变量获取,例如:
- 应用的启动脚 本是哪个文件,启动时指定了哪些参数
- 加载了哪些配置文件,导入了哪些配置
- 连了哪个数据库
- 有哪些public的工具类、常量
- 应用跑再哪个机器上,IP多少,内存多大
- g 变量
- g作为flask程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据
- g保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread_id区别
- current_app
- 使用方法
- current_app.name 获取应用名
- current_app.test_value='value' 给应用实例添加变量
- g 变量
- 使用方法
- g.name 获取g的name属性
- g.name='abc' 添加g全局变量name
- 请求上下文
- 概念
- Flask从客户端收到请求时,要让视图函数能访问一些对象,这样才能处理请求。请求对象是一个很好的例子,它封装了客户端发送的HTTP请求。
- 要想让视图函数能够访问请求对象,一个 显而易见的方式是将其作为参数传入视图函数,不过这会导致程序中的每个视图函数都增加一个参数,除了访问请求对象,如果视图函数在处理请求时还要访问其他对象,情况会变得更糟。为了避免大量可有可无的参数把视图函数弄得一团糟,Flask使用上下文临时把某些对象变为全局可访问。
- 只有在程序完全运行起来之后才能调用
- 请求上下文包含
- request
- 封装了HTTP请求的内容,针对的是http请求
- session
- 用来记录请求会话中的信息,针对的是用户信息
- request
- 使用方法
- 导入方式
- from flask import request
- 使用方法
- request.属性名 获取request上下文中的请求相关信息
- request对象的属性
- data 记录请求(请求发送的数据为raw_data)的数据, 数据类型为str
- form 记录请求(请求发送的数据为form_data)中的表单数据, 数据类型MultiDict
- args 记录请求中的查询参数,? 后面的查询字符串, 数据类型MultiDict
- cookies 记录请求中的cookie信息, 数据类型Dict
- headers 记录请求中的报文头, 数据类型EnvironHeaders
- method 记录请求使用的HTTP方法, 数据为GET/POST等
- url 记录请求的URL地址, 数据类型string
- files 记录请求上传的文件,为form表单中提交的文件对象组成的字典, 数据类型Dict
- json 获取前端传递过来的json字符串,并转换成dict类型
- session
- 使用方法
- 导入方式
- from flask import session
- 使用方法
- 使用方法参考session状态保持
- 请求上下文\应用上下文之间的区别
- 请求上下文:保存了客户端和服务器交互的数据
- 应用上下文:flask 应用程序运行过程中,保存的一些配置信息,比如程序名、数据库连接、应用信息等
- 视图函数返回内容
- 重定向redirect示例
- 重定向方法
- 跳转至其他url
- from flask import redirect
- return redirect('url') 在视图函数中通过redirect函数返回
- 跳转至其他路由
- 方法一:
- 这种方法不适用,因为当路由变化后,将不能成功的匹配到视图函数
- 方法二:
- from flask import url_for
- _external=True 参数表示已绝对路径的形式跳转,默认为相对路径的形式跳转
- 这种方法可以直接跳转到另一个视图函数去处理,尽管路由映射改变也不影响
- 返回JSON
- 返回json数据的方法
- from flask import jsonify
- return jsonify(<dict>) 在视图函数中通过jsonify函数返回
- 返回模板
- 返回模板的方法
- from flask import Flask, render_template
- return render_template(template_name, **content)
- 备注:**content参数可以是任意个命名参数
- 示例:
- return render_template(remplate_name, key1=value1, key2=value2)
- 参数中的key1,key2便是模板中模板变量调用参数使用的名字
- 返回一个respones对象
- 返回的方法
- from flask import make_response
- response = make_response(params) params:普通python类型数据(需要转换成response对象)
- return response
- 返回状态码
- 返回的方法
- return response, status_code 在返回的响应后面接一个数字,代表响应的状态码
- 返回一个静态文件
- 返回静态文件的方法
- 状态保持
- 为什么状态保持
- 因为http是一种无状态协议,不会保持某一次请求所产生的信息,如果想实现状态保持,在开发中解决方式有:
- 状态保持实现两种方法
- cookie:数据存储在客户端,节省服务器空间,但是不安全
- session:会话,数据存储在服务器端
- 设置与获取cookie的方法
- 设置cookie的方法
- response.set_cookie('key', 'value', max_age=second)
- max_age: cookie最大生存时间,默认是关闭浏览器失效
- 获取cookie的方法
- request.cookies.get('key')
- 删除cookie
- response.delete_cookie('key')
- 设置与获取session的方法(默认是将session存储在cookie中的)
- 设置session的方法
- 配置SCRET_KEY,导入session方法
- app.config['SCRET_KEY'] = 'fadfas' 设置为任意不规则字符串
- from flask import session
- 设置session的方法
- 不带过期时间的设置方法
- session['key'] = value
- 带过期时间的设置方法
- app.permanent_session_lifetime = 数字 单位为秒
- 获取session的方法
- session.get('key')
- 删除session的方法
- session.pop('key')
- 通过使用redis,将session存储在redis中
异常的捕获
- 抛出异常(状态码异常)
- 抛出异常的方法
- 通过调用abort()方法,抛出一个给定状态代码的 HTTPException
- 代码示例
- from flask import abort
- abort(500) # 抛出一个状态码为500的HTTPException异常
- 捕获异常
- 捕获异常的方法
- 注册一个错误处理程序,当程序抛出指定错误状态码或者指定的异常的时候,调用该装饰器所装饰的方法
- 装饰器接收的参数可以是:1.错误状态码;2.程序抛出的异常对象
- 捕获到的异常对象对传递给处理程序,程序需要用一个形参来接收
- 可以将异常对象return回去,会将异常信息字符串返回给客户端
- 代码示例
- @app.errorhandler(500) 注册异常处理程序,传入错误状态码\ 指定错误异常类
- def internal_server_error(e): 定义一个异常处理程序
- return '服务器搬家了'
请求钩子
- 请求钩子作用
- 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理
- 通过装饰器装饰处理函数的方式,在每次请求的过程中插入对应的处理程序
- 比如:在请求开始时,建立数据库连接;在请求结束时,指定数据的交互格式。为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。
- 四种请求钩子的实现
- before_first_request:在处理第一个请求前运行。
- 使用场景:可以在第一次请求到达的时候,开启数据库,一些初始化操作等
- before_request:在每次请求前运行。
- 注意:
- 可以在处理函数中,直接return一个response对象,那样便不会执行view函数,会直接去调用after_request
- 使用场景:判断访问我们服务器的客户端的身份,如果身份验证通过再将请求传递给路由
- after_request:如果没有未处理的异常,在每次请求后运行。
- 注意:
- 会传递给处理函数一个response对象,处理函数需要接收此参数
- 一定要return一个response对象,不然客户端接收不到服务器端的响应
- 使用场景: 比如将批量视图函数返回的响应,加上统一的请求头,设置cookie等;
- teardown_request:在每次请求后运行,即使有未处理的异常抛出。
- 备注:
- 会传递给处理函数一个异常对象参数,处理函数需要接收此参数
- 如果要针对异常返回给客户端响应,可以return一个异常信息的response
- 使用场景:当捕获到未处理的异常后,可以根据异常的信息返回给客户端错误的提示
生成铭文进行加密和解密
- 导入模块
- from werkzeug.security import generate_password_hash, check_password_hash
- 对密码进行铭文加密
- password_hash = generate_pass_hash(加密前的密码)
- 对加密后的密码与未加密字符串匹配(匹配返回True,失败返回False)
- password = check_password_hash(加密后的字符串,待校验的密码)