Flask蓝图,Session,闪现,中间件等

Posted 编程面试宝典

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask蓝图,Session,闪现,中间件等相关的知识,希望对你有一定的参考价值。

技术文章第一时间送达!

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__(selfinitial=Nonesid=None):
                    self.sid = sid
                    self.initial = initial
                    super(MySession, self).__init__(initial or ())


                def __setitem__(selfkeyvalue):
                    super(MySession, self).__setitem__(keyvalue)

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

                def __delitem__(selfkey):
                    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(datasid=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=domainpath=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

大型:

Flask蓝图,Session,闪现,中间件等

Flask蓝图,Session,闪现,中间件等

Flask蓝图,Session,闪现,中间件等

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

其他:

蓝图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()

运行结果:

Flask蓝图,Session,闪现,中间件等

还有一个@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,闪现,中间件等的主要内容,如果未能解决你的问题,请参考以下文章

Flask框架 之 功能详解

Flask框架cbv的写法请求与响应请求扩展session源码分析闪现

11.4 Flask session,闪现

python-flask复习—— 装饰器的坑及解决办法flask中的路由/实例化配置/对象配置/蓝图/特殊装饰器(中间件重定义错误页面)

flask之闪现

Flask框架—— 反向解析配置信息路由系统模板请求响应闪现请求扩展session