flask-session

flask-session就是将session中而不再是放到浏览器的cookie中了

要使用flask-session首先需要安装一下

pip3 install flask-session

如果想要将session放到redis中,当然是要配置一下了

from flask import Flask,session
from flask_session import RedisSessionInterface

app = Flask(__name__)
app.secret_key='djksahdk'

#默认方式保存session,是将session保存到浏览器的cookie中的
# from flask.sessions import SecureCookieSessionInterface
# app.session_interface=SecureCookieSessionInterface()

#方式一: redis保存session
# from redis import Redis
# app.session_interface=RedisSessionInterface(
#     redis=Redis(host='127.0.0.1',port=6379),        #连接redis
#     key_prefix = "dsjfal"   #这个前缀可以随便写,在save_session时,会用前缀+sid这个随机字符串
# )

# 方式二: redis保存到session
from flask.ext.session import Session
from redis import Redis
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379')
Session(app)



@app.route('/login')
def login():
    session['k1'] = 123
    return 'login'

@app.route('/index')
def index():
    v =session['k1']
    print(v)
    return 'index'


if __name__ == '__main__':
    app.run()
View Code

flask-session的作用:将默认保存在签名cookie中的值,保存到 redis/memcached/file/mongodb/sqlalchemy中 

flask中自带的session其实是通过app.session_interface = SecureCookieSessionInterface()来实现的对session的操作,如果我想使用flask-session,只需要将SecureCookieSessionInterface给换成是RedisSessionInterface就可以了.那么flask_session中都做了什么呢

flask_session中有也有两个函数open_session和save_session,先来看open_session中干了什么.

 

    def open_session(self, app, request):
        sid = request.cookies.get(app.session_cookie_name)
        if not sid:
            sid = self._generate_sid()  
            return self.session_class(sid=sid, permanent=self.permanent)
        if self.use_signer:
            signer = self._get_signer(app)
            if signer is None:
                return None
            try:
                sid_as_bytes = signer.unsign(sid)
                sid = sid_as_bytes.decode()
            except BadSignature:
                sid = self._generate_sid()
              #请求第一次来,返回一个特殊的字典: sid = dlasjfas
return self.session_class(sid=sid, permanent=self.permanent) if not PY2 and not isinstance(sid, text_type): sid = sid.decode('utf-8', 'strict') val = self.redis.get(self.key_prefix + sid) if val is not None: try: data = self.serializer.loads(val) return self.session_class(data, sid=sid) except: return self.session_class(sid=sid, permanent=self.permanent) return self.session_class(sid=sid, permanent=self.permanent)
sid = request.cookies.get(app.session_cookie_name)是获取浏览器中发过来的session中的value,我们想把session放到redis中,请求第一次过来,session是没有值的,如果第一次访问没有session的值,就会执行
signer = self._get_signer(app),_get_signer(app)就会获取到一个唯一标识,然后返回一个特殊的字典放到Local()中
    def _generate_sid(self):
        return str(uuid4())

视图中对session进行操作,例如设置了session['k1']=v1,视图处理完成,在返回数据给浏览器之前要执行save_session

    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)    #取当前的域名
        path = self.get_cookie_path(app)      #取cookie的地址
        if not session:
            if session.modified:
                self.redis.delete(self.key_prefix + session.sid)
                response.delete_cookie(app.session_cookie_name,
                                       domain=domain, path=path)
            return


        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        expires = self.get_expiration_time(app, session)    #过期时间
        val = self.serializer.dumps(dict(session))      #进行序列化
        self.redis.setex(name=self.key_prefix + session.sid, value=val,
                         time=total_seconds(app.permanent_session_lifetime))
        if self.use_signer:
            session_id = self._get_signer(app).sign(want_bytes(session.sid))
        else:
            session_id = session.sid
        response.set_cookie(app.session_cookie_name, session_id,
                            expires=expires, httponly=httponly,
                            domain=domain, path=path, secure=secure)

 

由于现在session中有值,就不走判断,继续往下执行,val = self.serializer.dumps(dict(session))是对session进行序列化,序列化的方式是pickle,通过pickle把这个字典进行了序列化,此时这个字典是{sid:'xxx','k1':'v1'}

serializer = pickle

 

将序列化之后的session字符串设为值,前缀(self.key_prefix)和sid为键,把它放到redis中

self.redis.setex(name=self.key_prefix + session.sid, value=val,
                         time=total_seconds(app.permanent_session_lifetime))

 

然后将session的唯一标识sid保存到浏览器的session中

response.set_cookie(app.session_cookie_name, session_id,
                            expires=expires, httponly=httponly,
                            domain=domain, path=path, secure=secure)

 flask-session中的注意事项:

  1.session中存储的是字典,那么修改字典中的元素时,会造成数据不更新

   解决方法是: 方法一:在设置过session后,再写上session['modified']=True

        方法二:在settings中设置SESSION_REFRESH_EACH_REQUEST= True 并且在用户验证成功之后写上session.permanent=True(redis中默认是True)

 

小应用:

目录结构:

from datetime import timedelta
from redis import Redis

class Config(object):
    DEBUG = True
    SECRET_KEY = "dsjlajfla"
    PERMANENT_SESSION_LIFETIME = timedelta(minutes=20)  #设置session超时时间是20分钟,20分钟之后就失效了
    # 如果写上下面这一句还需要在用户登录成功之后写上session.permanent=True,才能对session的二级数据进行修改
    SESSION_REFRESH_EACH_REQUEST = True  #每次请求过来都刷新session,就不会存在session['user_info']['k'] =v不能修改的问题了,如果不写这一句,需要在修改之后加上一个session['modified']= True
    SESSION_TYPE = 'redis'


# 正式环境连接redis
class ProductionConfig(Config):
    SESSION_REDIS = Redis(host='192.168.0.11',port='6379')


#开发环境
class DevelopmentConfig(Config):
    SESSION_REDIS = Redis(host='127.0.0.1',port='6379')



class TestingConfig(Config):
    pass
settings
from  flask_pro import create_app

app = create_app()

if __name__ == '__main__':
    app.run()
manage.py
from flask import Flask
from .views import account
from .views import home
# from flask.ext.session import Session
from flask_session import Session

def create_app():
    app = Flask(__name__)
    #引入配置文件settings
    app.config.from_object("settings.DevelopmentConfig")    #引入配置文件
    
    app.register_blueprint(account.account)
    app.register_blueprint(home.home)
    
    # 将默认使用的session替换成redis session
    Session(app)
    return app
__init__.py
from flask import Blueprint,request,render_template,session,redirect
from uuid import uuid4

account = Blueprint('account',__name__)


@account.route('/login',methods=['GET','POST'])
def login():
    if request.method == "GET":
        return render_template('login.html')
    user = request.form.get('user')
    pwd = request.form.get('pwd')
    print(user,pwd)

    if user=='alex' and pwd=='123':
        uid = str(uuid4())
        session.permanent=True      #flask默认的session中该值默认是Flase,如果不设置,虽然在配置文件中设置了每次请求刷新session,依然是不能对session字典中的元素进行修改
                                    #flask-session中这个值默认是True,的
        session['user_info'] = {'id':uid,'name':user}
        print(session['user_info'])
        
        session['user_info']['name']='huahua'
        # session['modified'] = True        #一般不用这种方式,虽然这种方式也可以实现,但在配置中写SESSION_REFRESH_EACH_REQUEST=True这种方式更好,
        print(session['user_info'])
        return redirect('/index')
    else:
        return render_template('login.html',msg="用户名或密码错误")
views/account.py
from flask import Blueprint,request,render_template,session,redirect

home = Blueprint('home',__name__)

@home.route('/index')
def index():
    user_info= session.get('user_info')
    print(user_info)
    return render_template('index.html')
views/home.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
<form action="" method="post">
    <input type="text" name="user">
    <input type="password" name="pwd">
    <input type="submit" value="提交 "> {{msg}}

</form>


</body>
</html>
templates/login.html

 

posted @ 2018-05-26 18:28  dwenwen  阅读(138)  评论(0编辑  收藏  举报