本节内容
- 请求钩子
- request
- 状态保持(cookie,session)
- 上下文
- flask_script
- jinja2模板引擎
请求钩子
在flask中为避免代码的重复,flask提供了统一的接口可以添加这些处理函数,即请求钩子。
请求钩子:
交互过程中,有一些准备或扫尾工作需要:
比如请求开始时要进行datebase的连接,auth的认证等
请求结束的时候指定数据的交互格式。
请求钩子通过 装饰器 实现的
- before_first_request:在第一次请求之前调用(在处理第一个请求之前执行),可以在此方法内部做一些初始化操作
- before_request:在每次请求之前执行,如果在某修饰的函数中返回了一个response,视图函数将不会被调用
- after_request:在执行完视图函数之后调用,并且会把视图函所生成的响应传入,可以在此方法中对响应做最后一步的统一处理。ps:如果视图函数出错,则不执行该函数。
- teardown_request:在每次请求之后执行,接收一个参数--错误信息。如果有相关的错误就会抛出。
@app.before_first_request
def before_first_request():
print('before_first_request')
@app.before_request
def before_request():
print('before_request')
@app.after_request
def after_request(response):
print('after_request')
#把响应内容header部分的Content-Type改为applcation/json
response.headers['Content-Type'] = "application/json"
return response
@app.teardown_request
def teardown_request(response):
print('teardown_request')
@app.route('/')
def index():
return 'index'
运行:
Content-type被更改:
request
状态保持
http是一种无状态协议
- 无状态: ----> 用户一次请求,浏览器,服务器无法知道之前用户做过什么。因为浏览器和服务器之间使用socket通信。
对于无状态协议的理解,看做以下五条
1、协议对于事务处理没有记忆能力
2、对同一个url请求没有上下文关系
3、每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况
4、服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器
5、人生若只如初见:比如商品加入购物车,重登后购物车里的东西无了
cookie:数据存储在客户端,节省服务器空间,但是不安全
session:会话,数据存储在服务器端
cookie:
#cookie
from flask import Flask, make_response, request # django中的httpresponse
app = Flask(__name__)
#设置cookie
@app.route('/cookie')
def set_cookie():
resp = make_response('this is set cookie')
resp.set_cookie('username','laoma',max_age = 3600) #max_age:cookie事件
return resp
#获取cookie
@app.route('/request')
def get_cookie():
response = request.cookies.get('username') #获取之前设置的cookie
return response
if __name__ == '__main__':
app.run()
运行:
过期时间默认为浏览器会话结束:
注:我们可以自己设计cookie的时间(利用max_age关键字)设置时间之后,再次运行:
访问:
127.0.0.1:5000/request
获取到cookie的值:
session
session会话主要用于存储敏感涉密信息,例如:个人信息、账户余额、验证码等问题,session依赖于cookie,在TensorFlow中,也会使用session尽管和web中的session有所不同,但也可理解为会话方式。
#session 会话(重要信息),依赖于cookie
#设置session
@app.route('/index1')
def index1():
session['lefmoney'] = '99999' #设置session的键和值
return redirect(url_for('index')) #重定向到index函数中
app.secret_key = 'fdsofof' #用于一些模块的 hash
@app.route('/')
def index():
return session.get('lefmoney','none') #默认为0
Session, Cookies以及一些第三方扩展都会用到SECRET_KEY值,这是一个比较重要的配置值,应该尽可能设置为一个很难猜到的值,随机值更佳。随机的问题在于很难判断什么是真随机。一个密钥应该足够随机。你的操作系统可以基于一个密码随机生成器来生成漂亮的随机值,这个值可以用来做密钥;
SECRET_KEY配置变量是通用密钥, 可在 Flask 和多个第三方扩展中使用. 如其名所示, 加密的强度取决于变量值的机密度. 不同的程序要使用不同的密钥, 而且要保证其他人不知道你所用的字符串.其主要作用应该是在各种加密过程中加盐以增加安全性。在实际应用中最好将这个参数存储为系统环境变量。当然我们也可以利用加密哈希,就是让cookie变得“安全”的字段。服务器向我们发送最新的会话数据之前,会结合我们的会话数据、当前时间戳以及服务器的私钥来计算哈希从而加密session,使得会话变得安全。
快速入门中的 “ 会话”部分对应设置哪种服务器端机密提供了很好的建议。加密取决于机密;如果你没有设置要使用的加密服务器端密码,那么每个人都可以破坏你的加密;就像你计算机的密码一样。秘密加上要签名的数据用于创建签名字符串,使用密码哈希算法很难重新创建值;仅当你具有完全相同的机密且原始数据时,你才能重新创建此值,让Flask检测是否未经许可对任何内容进行了更改。由于Flask永远不会将秘密包含在发送给客户端的数据中,因此客户端无法篡改会话数据,并希望产生新的有效签名。
Flask尽量使用该itsdangerous库来完成所有艰苦的工作;会话使用带有自定义JSON序列化程序的itsdangerous.URLSafeTimedSerializer类。
运行:
没有session:
进入index1设置session:
取到session:
上下文
- request context :请求上下文 -- 包含 cookie 和 session
例如:resp = request.cookies.get()
等获取上下文方式。 - application context : 应用上下文 -- current_app 和 g
current_app和g都属于应用上下文对象。
1、current_app:表示当前运行程序文件的程序实例。
2、g:(global) 处理请求时,用于临时存储的对象,每次请求都会重设这个变量。比如:我们可以获取一些临时请求的用户信息。当调用app = Flask(name)的时候,创建了程序应用对象app;
request 在每次http请求发生时,WSGI server调用Flask.call();然后在Flask内部创建的request对象;
app的生命周期大于request和g,一个app存活期间,可能发生多次http请求,所以就会有多个request和g。
最终传入视图函数,通过return、redirect或render_template生成response对象,返回给客户端。
区别: 请求上下文:保存了客户端和服务器交互的数据。 应用上下文:在flask程序运行过程中,保存的一些配置信息,比如程序文件名、数据库的连接、用户信息等。
实例:
@app.route('/')
def index():
print(current_app.name)
return session.get('lefmoney','none') #默认为0
运行:
打印出当前运行的文件名:
flask_script
首先安装flask_script
pip install flask_script
demo_flask_script.py:
from flask_script import Manager
from flask import Flask
app = Flask(__name__)
#Manager和app关联
manager = Manager(app)
@app.route('/')
def index():
return 'haha1'
if __name__ == '__main__':
manager.run()
在terminal中:
python demo_flask_script.py runserver -h 127.0.0.1 -p 5001
可以使用命令行进行启动
jijia2模板引擎
参考Django,Jinja2的模板语法与Django的模板内容基本相似
语法:
- 变量取值{{ }}、
- 控制结构{% %}、
-
注释{# #}
模板语言的选择:
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def index():
#String
my_str = 'zhangsan'
#num
my_num = 100
#列表
my_list = [i for i in range(9)]
#字典
my_dict = {'name':'老亚瑟','age':18}
#使用render_template进行模板渲染
#在django中使用的是render
return render_template('temp_demo1.html',
my_str = my_str,
my_num = my_num,
my_list = my_list,
my_dict = my_dict
)
if __name__ == '__main__':
app.run()
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>jinja2</h1>
游戏名:{{ my_str }}
<br>
数字:{{ my_num }}
<br>
列表:{{ my_list }}
<br>
字典:{{ my_dict }}
<br>
my_num +10 = {{ my_num + 10 }}
<br>
my_num + array[0] = {{ my_num + my_list[1] }}
<br>
{{ my_list.1 }}
{{ my_list[1] }}
<br>
{{ my_dict['name'] }}
{{ my_dict.name }}
</body>
</html>
运行:
网友评论