Session

除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。

设置:session['username'] = 'xxx'

删除:session.pop('username', None)

from flask import Flask,url_for,session

app = Flask(__name__)
app.secret_key = "sdsfdgdgdgd"
app.config['SESSION_COOKIE_NAME'] = 'session_lvning'  #设置session的名字

@app.route('/index/')
def index(nid):
    #session本质上操作的是字典, 所有对session操作的方法与字典方法相同
    #session的原理:如果下一次访问的时候带着随机字符串,会把session里面对应的
    # 值拿到内存,假设session保存在数据库,每执行一次链接一次数据库,每次都要时时更新的话,会非常损耗数据库的效率
    session["xxx"] = 123
    session["xxx2"] = 123
    session["xxx3"] = 123
    session["xxx4"] = 123
    del session["xxx2"]  #在这删除了,真正存储的时候是没有xxx2的
    return "ddsf"

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

关于session的配置

app.config['SESSION_COOKIE_NAME'] = 'session_lvning'

- session超时时间如何设置?      'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)
 以下是跟session相关的配置文件
"""
            'SESSION_COOKIE_NAME':                  'session',
            'SESSION_COOKIE_DOMAIN':                None,
            'SESSION_COOKIE_PATH':                  None,
            'SESSION_COOKIE_HTTPONLY':              True,
            'SESSION_COOKIE_SECURE':                False,
            'SESSION_REFRESH_EACH_REQUEST':         True,  #是否每次都跟新
            'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)

基本使用

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

自定义Session

pip3 install Flask-Session

        run.py
            from flask import Flask
            from flask import session
            from pro_flask.utils.session import MySessionInterface
            app = Flask(__name__)

            app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
            app.session_interface = MySessionInterface()

            @app.route('/login.html', methods=['GET', "POST"])
            def login():
                print(session)
                session['user1'] = 'alex'
                session['user2'] = 'alex'
                del session['user2']

                return "内容"

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

        session.py
            #!/usr/bin/env python
            # -*- coding:utf-8 -*-
            import uuid
            import json
            from flask.sessions import SessionInterface
            from flask.sessions import SessionMixin
            from itsdangerous import Signer, BadSignature, want_bytes

            class MySession(dict, SessionMixin):
                def __init__(self, initial=None, sid=None):
                    self.sid = sid
                    self.initial = initial
                    super(MySession, self).__init__(initial or ())

                def __setitem__(self, key, value):
                    super(MySession, self).__setitem__(key, value)

                def __getitem__(self, item):
                    return super(MySession, self).__getitem__(item)

                def __delitem__(self, key):
                    super(MySession, self).__delitem__(key)

            class MySessionInterface(SessionInterface):
                session_class = MySession
                container = {}

                def __init__(self):
                    import redis
                    self.redis = redis.Redis()

                def _generate_sid(self):
                    return str(uuid.uuid4())

                def _get_signer(self, app):
                    if not app.secret_key:
                        return None
                    return Signer(app.secret_key, salt='flask-session',
                                  key_derivation='hmac')

                def open_session(self, app, request):
                    """
                    程序刚启动时执行,需要返回一个session对象
                    """
                    sid = request.cookies.get(app.session_cookie_name)
                    if not sid:
                        sid = self._generate_sid()
                        return self.session_class(sid=sid)

                    signer = self._get_signer(app)
                    try:
                        sid_as_bytes = signer.unsign(sid)
                        sid = sid_as_bytes.decode()
                    except BadSignature:
                        sid = self._generate_sid()
                        return self.session_class(sid=sid)

                    # session保存在redis中
                    # val = self.redis.get(sid)
                    # session保存在内存中
                    val = self.container.get(sid)

                    if val is not None:
                        try:
                            data = json.loads(val)
                            return self.session_class(data, sid=sid)
                        except:
                            return self.session_class(sid=sid)
                    return self.session_class(sid=sid)

                def save_session(self, app, session, response):
                    """
                    程序结束前执行,可以保存session中所有的值
                    如:
                        保存到resit
                        写入到用户cookie
                    """
                    domain = self.get_cookie_domain(app)
                    path = self.get_cookie_path(app)
                    httponly = self.get_cookie_httponly(app)
                    secure = self.get_cookie_secure(app)
                    expires = self.get_expiration_time(app, session)

                    val = json.dumps(dict(session))

                    # session保存在redis中
                    # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
                    # session保存在内存中
                    self.container.setdefault(session.sid, val)

                    session_id = self._get_signer(app).sign(want_bytes(session.sid))

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

第三方session

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
pip3 install redis
pip3 install flask-session

"""

from flask import Flask, session, redirect
from flask.ext.session import Session

app = Flask(__name__)
app.debug = True
app.secret_key = 'asdfasdfasd'

app.config['SESSION_TYPE'] = 'redis'
from redis import Redis
app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379')
Session(app)

@app.route('/login')
def login():
    session['username'] = 'alex'
    return redirect('/index')

@app.route('/index')
def index():
    name = session['username']
    return name

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

Django和Flask中session的区别

Django中,session保存在服务端的数据库中,数据库中保存请求用户的所有数据,服务端数据中{'随机字符串':加密后的客户相关信息}
请求完成后,把随机字符串作为值,返回给客户端,保存在客户端的cookie中,键为:sessionid,值为:服务端返回的随机字符串;即{'sessionid':'随机字符串'}

Flask中,服务端什么都不存,用户第一次请求时,在内存中生成一个空字典,将这个空字典加密后,返回给客户端,保存在客户端的cookie中,键为’session',值为:加密后的字典
下次访问时,读取客户端cookie中key为session对应的值
然后进行解密(如果不能按之前的的加密方式对应个解密方式解密,即认为第一次请求,重新生成空字典),解密成功后,可以对字典进行操作,保存新数据在字典中,请求完成后,会重新加密这个字典,返回个客户端保存

蓝图(flask中多py文件拆分都要用到蓝图)

如果代码非常多,要进行归类。不同的功能放在不同的文件,吧相关的视图函数也放进去。蓝图也就是对flask的目录结构进行分配(应用于小,中型的程序)

蓝图用于为应用提供目录划分:

小中型:

manage.py

import fcrm
if __name__ == '__main__':
    fcrm.app.run()

__init__.py(只要一导入fcrm就会执行init.py文件)

from flask import Flask
#导入accout 和order
from fcrm.views import accout
from fcrm.views import order
app = Flask(__name__)
print(app.root_path)  #根目录

app.register_blueprint(accout.accout)  #把蓝图注册到app里面,accout.accout是创建的蓝图对象
app.register_blueprint(order.order)

accout.py

from flask import  Blueprint,render_template
accout = Blueprint("accout",__name__)

@accout.route('/accout')
def xx():
    return "accout"

@accout.route("/login")
def login():
    return render_template("login.html")

order.py

from flask import Blueprint
order = Blueprint("order",__name__)

@order.route('/order')
def register():   
    return "order

大型:

注意:
蓝图中的视图函数的名字不能和蓝图对象的名字一样!!!

其他:

蓝图URL前缀:xxx = Blueprint('account', __name__,url_prefix='/xxx')
蓝图子域名:xxx = Blueprint('account', __name__,subdomain='admin')
# 前提需要给配置SERVER_NAME: app.config['SERVER_NAME'] = 'hc.com:5000'
# 访问时:admin.hc.com:5000/login.html

闪现(flash)

session存在在服务端的一个字典里面,session保存起来,取一次里面还是有的,直到你删除之后才没有了

1、本质

flash是基于session创建的,flash支持往里边放值,只要你取一下就没有了,相当于pop了一下。不仅可以拿到值,而且可以把其从session里的去掉,
基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。

2、闪现的用途
某个数据仅需用一次时,可以使用闪现

from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'

@app.route('/users')
def users():
    # 方式一
    # msg = request.args.get('msg','')
    # 方式二
    # msg = session.get('msg')
    # if msg:
    #     del session['msg']
    # 方式三
    v = get_flashed_messages()  # 获取flash中的值
    print(v)
    msg = ''
    return render_template('users.html',msg=msg)

@app.route('/useradd')
def user_add():
    # 在数据库中添加一条数据
    # 假设添加成功,在跳转到列表页面时,显示添加成功
    # 方式一
    # return redirect('/users?msg=添加成功')
    # 方式二
    # session['msg'] = '添加成功'
    # 方式三
    flash('添加成功')
    return redirect('/users')

if __name__ == '__main__':
    app.run(debug=True)

中间件

在函数执行之前或函数执行之后想做点事情,有2种方式

第一种:装饰器

第二种:flask里面的扩展,相当于django中的中间件

from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'

@app.before_request
def process_request1():
    print('process_request1')

@app.after_request
def process_response1(response):
    print('process_response1')
    return response

@app.before_request
def process_request2():
    print('process_request2')

@app.after_request
def process_response2(response):   #参数也得有
    print('process_response2')
    return response   #必须有返回值

@app.route('/index')
def index():
    print('index')
    return 'Index'

@app.route('/order')
def order():
    print('order')
    return 'order'

@app.route('/test')
def test():
    print('test')
    return 'test'

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

运行结果:

还有一个@app.before_first_request:表示,当程序运行起来,第一个请求来的时候就只执行一次,下次再来就不会在执行了

请求扩展

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, Request, render_template

app = Flask(__name__, template_folder='templates')
app.debug = True

@app.before_first_request    # 只在第一次请求到来时执行一次,后面不会再执行
def before_first_request1():
    print('before_first_request1')

@app.before_first_request
def before_first_request2():
    print('before_first_request2')

@app.before_request    # 每次请求到来时,都会执行
def before_request1():
    Request.nnn = 123
    print('before_request1')

@app.before_request
def before_request2():
    print('before_request2')

@app.after_request    # 每次响应时执行
def after_request1(response):
    print('before_request1', response)
    return response

@app.after_request
def after_request2(response):
    print('before_request2', response)
    return response

@app.errorhandler(404)
def page_not_found(error):
    return 'This page does not exist', 404

@app.template_global()    # 自定义标签,所有页面都直接使用
def sb(a1, a2):
    return a1 + a2

@app.template_filter()    # 自定义过滤器,所有页面都直接使用
def db(a1, a2, a3):
    return a1 + a2 + a3

@app.route('/')    # 访问的url,不加其他后缀时,也要有/
def hello_world():
    return render_template('hello.html')

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

自定义标签和过滤器在页面上的调用方式:{{sb(1,2)}}  {{ 1|db(2,3)}}

编写统一的404页面

导入abort方法
    from flask import abort

设置一个站位符,当404错误出现时,自己编写的404页面就会在占位符的位置进行显示
    abort(404)  

利用钩子编写自己的404页面

@app.errorhandler(404)  # 404页面钩子
def page_404(er):  # 参数是原始的404页面提示信息
  print(er)
  return '这是统一的错误页面', 404, {}  # 返回自己编写的404页面信息


from flask import Flask
from flask import abort

app = Flask(__name__)

@app.route('/')
def index():
    return '测试主页面'

movies = [1,2,3,4,5]

@app.route('/movie/<int:num>/')
def movie(num):
    if num in movies:
        return '电影 {} 的详细信息为:...... '.format(num)
    abort(404)  # 自己编写的404页面会显示在这里

@app.errorhandler(404)  # 404页面钩子
def page_404(er):  # 参数是原始的404页面提示信息
    print(er)
    return '这是统一的错误页面', 404, {}  # 返回自己编写的404页面信息

print(app.url_map)

if __name__ == '__main__':
    app.run(debug=True)

原文链接:

https://www.cnblogs.com/huchong/p/8227606.html


识别图中二维码,领取python全套视频资料

Flask蓝图,Session,闪现,中间件等的更多相关文章

  1. Flask蓝图目录、Flask-SQLAlchemy、Flask-Script、Flask-Migrate

    一.Flask蓝图目录 我们之前写的Flask项目都是自己组织的目录结构,其实Flask官方有其推荐的目录结构,以下就是一个符合官方推荐的Flask小型应用的项目结构目录示例,如下: 如图,这就是我们 ...

  2. Flask蓝图Blueprint和特殊装饰器

    Flask 中的 蓝图 Blueprint 不能被run的flask实例:相当于django中的app01 应用 蓝图作用:功能隔离 路由隔离 Blueprint就是 一个不能run的flask 蓝图 ...

  3. flask之session

    ''' session使用: session创建: (1)导入session from flask import session (2)设置secret_key密钥 app.secret_key='s ...

  4. Flask的session——关于写扩展所学习到的

    这两天端午节.趁着端午节没事干,写了个flask的扩展--flask-RedisSession 在flask中使用该扩展可以让你借助redis数据库轻松获得server-side session. 这 ...

  5. Flask 蓝图(Blueprint)

    蓝图使用起来就像应用当中的子应用一样,可以有自己的模板,静态目录,有自己的视图函数和URL规则,蓝图之间互相不影响.但是它们又属于应用中,可以共享应用的配置.对于大型应用来说,我们可以通过添加蓝图来扩 ...

  6. Flask的session使用

    由于http是无状态保存的协议,session可以看作不同请求之间保存数据的一种机制.flask的session是基于cookie的会话保持. 流程 当客户端进行第一次请求的时候,客户端的HTTP r ...

  7. FLASK 的Session和MoudelForm插件

    falsk是小而精的框架,但是热度高, 所有很多爱好者提供了很多扩展插件 功能强大,美而不足的就是兼容稳定性有时候不太好,不过大部分还是很可以的 Flask-Session flask内置sessio ...

  8. 第六篇 flask中session

    Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 Flask 中 session 的使用 1. Flask 中 session 是 ...

  9. Flask里面session的基本操作

    #session是依赖于flask的session模块 #如果想使用session模块,在配置里必须定义sessionkey from flask import Flask,session #建立对象 ...

随机推荐

  1. notification 报错the method build() is undefined for the type Notificatin.Builder

    notification 报错the method build() is undefined for the type Notificatin.Builder 这事api版本号太低导致的 Notifi ...

  2. selenuim爬虫实战 (下)

    SuperLOFTERDownloader7.java package test; import java.io.IOException; import java.util.ArrayList; im ...

  3. JsonNode、JsonObject常用方法

    最近项目中要用json,闲暇时间,对json进行下总结. 1.JsonNode 项目中用到的jar包   import com.fasterxml.jackson.core.JsonParseExce ...

  4. 代码大全(code complete) 有感

    软件开发的工作内容 问题定义 需求分析 实现计划 总体设计 详细设计 创建即实现(编码和调试) 系统集成 单元测试 校正性维护 功能强化 隐喻 好比监听器看做是某单位的看门老大爷 这里的类比: 通过把 ...

  5. JQuery Show()的几种效果 总有一种是你需要的

    1 show()方法和hide()方法 $("selector").show()  从display:none还原元素默认或已设置的display属性$("selecto ...

  6. thinkphp 使用外部php或html 原理

  7. [转载]Jenkins持续集成项目搭建与实践——基于Python Selenium自动化测试 -2

    自己的代码 import unittest # import HTMLTestRunner_cn as HTMLTestRunner import xmlrunner import sys sys.p ...

  8. 【BZOJ】2005: [Noi2010]能量采集(欧拉函数+分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2005 首先和某题一样应该一样可以看出每个点所在的线上有gcd(x,y)-1个点挡着了自己... 那么 ...

  9. 线程本地变更,即ThreadLocal-->Spring事务管理

    我们知道Spring通过各种模板类降低了开发者使用各种数据持久技术的难度.这些模板类都是线程安全的,也就是说,多个DAO可以复用同一个模板实例而不会发生冲突.我们使用模板类访问底层数据,根据持久化技术 ...

  10. ASP.NET MVC:Expression Trees 作为参数简化查询

    ASP.NET MVC 引入了 ModelBinder 技术,让我们可以在 Action 中以强类型参数的形式接收 Request 中的数据,极大的方便了我们的编程,提高了生产力.在查询 Action ...