当前位置: 首页>后端>正文

flask session 保存失败 flask使用session

session的使用和原理


使用

# 全局引入
from flask import session
# 设置secret_key
app.secret_key='asdadasdasdasdaz'
# 设置session
session['']=''
# 取值
res=session['']

原理

flask session 保存失败 flask使用session,flask session 保存失败 flask使用session_redis,第1张

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)}}

总结

  1. 重点掌握before_request和after_request,
  2. 注意有多个的情况,执行顺序
  3. 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)




https://www.xamrdz.com/backend/38a1964216.html

相关文章: