session的使用和原理
使用
# 全局引入
from flask import session
# 设置secret_key
app.secret_key='asdadasdasdasdaz'
# 设置session
session['']=''
# 取值
res=session['']
原理
flask的session源码分析
# app.session_interface---> SecureCookieSessionInterface()类的对象
-open_session:请求来了,从cookie中取出字符串,把字符串反序列化成session对象
-save_session:请求走,把session对象,序列化成字符串,放到cookie中
# open_session
def open_session(self, app, request):
s = self.get_signing_serializer(app)
if s is None:
return None
val = request.cookies.get(app.session_cookie_name)
if not val:
return self.session_class()
max_age = total_seconds(app.permanent_session_lifetime)
try:
data = s.loads(val, max_age=max_age)
return self.session_class(data)
except BadSignature:
return self.session_class()
# save_session
def save_session(self, app, session, response):
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
if not session:
if session.modified:
response.delete_cookie(
app.session_cookie_name, domain=domain, path=path
)
return
if session.accessed:
response.vary.add("Cookie")
if not self.should_set_cookie(app, session):
return
httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
samesite = self.get_cookie_samesite(app)
expires = self.get_expiration_time(app, session)
val = self.get_signing_serializer(app).dumps(dict(session))
response.set_cookie(
app.session_cookie_name,
val,
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure,
samesite=samesite,
)
闪现
闪现其实就是flash翻译过来的。
假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息,本质其实就是在a页面,把错误信息放到了某个位置,在b页面把错误取出来。
作用:在一次请求中,把一些数据放在闪现中,下次请求就可以从闪现中取出来,取一次就没了(使用分类也是这样)
# 本质就是放到session中了
#使用:
-放值
-flash(err)
-flash(err,category='lqz') # 分类
-取值
-get_flashed_messages()
-err = get_flashed_messages(category_filter=['lqz'])
# 等同于djagno的message框架
请求扩展
flask的请求扩展,装饰器,可以完成请求来了,请求走了,出异常了,页面找不到。。执行该装饰器装饰的函数,
before_request
-return四件套,不继续往下走了,如果retrun None,继续走下一个请求扩展
-请求来了,就会执行它
-多个before_request,会从上往下依次执行
after_request
-必须返回response对象
-请求走了,会执行它
-多个after_request,从下往上依次执行
before_first_request
-项目启动后,第一次访问,会执行
-返回None,会继续往下执行,返回四件套,就不继续往后走了
teardown_request
-无论程序是否出异常,都会触发它
-记录错误日志
-app.debug=False模式才行
errorhandler
-监听某个状态码,如果是这个状态码的错误,就会触发它的执行
-可以返回四件套,统一返回格式
template_global:标签
# 定义
@app.template_global()
def sb(a1, a2):
return a1 + a2
# 模板中使用
{{sb(1,2)}}
template_filter:过滤器
# 定义
@app.template_filter()
def db(a1, a2, a3):
return a1 + a2 + a3
# 模板中使用
{{ 1|db(2,3)}}
总结
- 重点掌握before_request和after_request,
- 注意有多个的情况,执行顺序
- before_request请求拦截后(也就是有return值),response所有都执行,django一样
蓝图
蓝图是Blue_print翻译过来的,作用是对目录进行划分。
不使用蓝图来划分目录,不太好,因为全局就一个app对象,导来导去,很容易出现循环导入的问题
-templates
-views
-__init__.py
-user.py
-order.py
-app.py
蓝图的使用步骤:
1 实例化得到蓝图对象 ---可以传一些参数:account = Blueprint('account', name,templates,static)
2 把蓝图对象在app中注册---》app.register_blueprint(account,制定前缀)
3 使用蓝图对象,注册路由
4 蓝图有自己的请求扩展--》app对象总的请求扩展,每个蓝图有自己的请求扩展
使用蓝图来做目录划分---》使用蓝图对象,取代app对象
使用蓝图的小型项目
-flask_pro #项目名
-pro_flask # 文件夹
-__init__.py # 包的init文件
-static #静态文件
-code.png
-templates #模板文件
-index.html
-views #视图函数写在里面
-account.py #订单相关视图函数
-blog.py #博客相关视图函数
-manage.py # 项目的启动文件
pro_flask/init.py
from flask import Flask
app = Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static')
from .views.account import account
from .views.blog import blog
# 注册3个蓝图,把他们注册进app中
app.register_blueprint(account)
app.register_blueprint(blog)
pro_flask/views/account.py
from flask import Blueprint
from flask import render_template
# 实例化得到蓝图对象
account = Blueprint('account', __name__)
@account.route('/login.html', methods=['GET', "POST"])
def login():
return render_template('login.html')
pro_flask/views/blog.py
from flask import Blueprint, render_template,request
blog = Blueprint('blog', __name__)
@blog.route('/get_blog')
def get_blog():
print(request.path)
return render_template('blog.html')
manage.py
from pro_flask import app
if __name__ == '__main__':
app.run()
使用蓝图的大型项目
pro_flask # 项目名
-pro_flask #包名
-admin #admin app的名字
-static #app自己的静态文件
-templates #app自己的模板文件
-__init__.py #包的init
-views.py #app自己的视图函数
-web #web app的名字
-static #app自己的静态文件
-templates #app自己的模板文件
-__init__.py #包的init
-views.py #app自己的视图函数
-__init__.py
-run.py
pro_flask/admin/init.py
from flask import Blueprint
# 第一步:初始化蓝图
admin = Blueprint(
'admin',
__name__,
template_folder='templates', # 指定该蓝图对象自己的模板文件路径
static_folder='static' # 指定该蓝图对象自己的静态文件路径
)
from . import views
pro_flask/admin/views.py
from . import admin
from flask import render_template
@admin.before_request
def before():
print('admin 的 before')
# 第三步:使用蓝图注册路由
@admin.route('/index')
def index():
return render_template('admin.html')
pro_flask/web/init.py
from flask import Blueprint
web = Blueprint(
'web',
__name__,
template_folder='templates',
static_folder='static'
)
from . import views
pro_flask/web/views.py
from . import web
@web.route('/index')
def index():
return 'Web.Index'
pro_flask/init.py
from flask import Flask
from .admin import admin
from .web import web
app = Flask(__name__)
app.debug = True
# 第二步:在app中注册蓝图
app.register_blueprint(admin, url_prefix='/admin') # url_prefix='/admin' 访问这个app的前缀,等同于include
app.register_blueprint(web)
run.py
from pro_flask import app
if __name__ == '__main__':
app.run()
g对象
flask 中有个 g 对象,在一次请求中,可以赋值,取值 :当次请求中得全局对象,在一次请求中放了值,后续就可以取出来
为什么不放在request中?为了防止值被覆盖掉request中原有的值。
g和session的区别?
-g只对当次请求有效
-session对这个人所有请求都有效
使用
from flask import Flask, g, request,session
app = Flask(__name__)
app.debug=True
@app.before_request
def before():
print(type(g)) # werkzeug.local.LocalProxy 代理模式
print(type(session))
print(type(request))
if request.path == '/':
# request.method='lqz'
g.name = 'lqz' # 放到g对象中
else:
# request.name = 'pyy'
g.name = 'pyy'
def add(a,b):
print(g.name)
# print('-----', request.name)
@app.route('/')
def index():
print(g.name)
# print('-----',request.name)
# add(1,2)
return 'hello'
@app.route('/home')
def home():
print(g.name)
return 'hello'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
flask-session的使用
session默认以cookie的形式放到浏览中,我们想把session,放到服务端保存(redis中,mysql中。。。)
只需要写一个类,写open_session和save_session方法.
使用flask-session
方式一:
from flask_session import RedisSessionInterface
app.session_interface=RedisSessionInterface(redis=None,key_prefix='luffy_') #redis为None自动连接本地redis,key_prefi为redis中Key的前缀
方式二:通用方案
from redis import Redis
from flask_session import Session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_KEY_PREFIX'] = 'luffy'
app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379')
Session(app) #后面会经常见这种写法--->类(app)---》包一下的写法
案例
from flask import Flask, g, request,session
app = Flask(__name__)
app.debug=True
app.secret_key='asdasdfasdf'
# 使用flask-session:方式一:
# from flask_session import RedisSessionInterface
# app.session_interface=RedisSessionInterface(redis=None,key_prefix='luffy_')
#方式二:通用方案
from redis import Redis
from flask_session import Session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_KEY_PREFIX'] = 'luffy'
app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379')
Session(app) #后面会经常见这种写法--->类(app)---》包一下的写法
@app.route('/set_session')
def set_session():
session['name']='lqz'
return '设置成功'
@app.route('/get_session')
def get_session():
print(session['name'])
return '获取成功'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)