Flask框架二

Flask配置文件

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
    {
        'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
        'TESTING':                              False,                          是否开启测试模式
        'PROPAGATE_EXCEPTIONS':                 None,                          
        'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
        'SECRET_KEY':                           None,
        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
        'USE_X_SENDFILE':                       False,
        'LOGGER_NAME':                          None,
        'LOGGER_HANDLER_POLICY':               'always',
        'SERVER_NAME':                          None,
        'APPLICATION_ROOT':                     None,
        '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,
        'MAX_CONTENT_LENGTH':                   None,
        'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
        'TRAP_BAD_REQUEST_ERRORS':              False,
        'TRAP_HTTP_EXCEPTIONS':                 False,
        'EXPLAIN_TEMPLATE_LOADING':             False,
        'PREFERRED_URL_SCHEME':                 'http',
        'JSON_AS_ASCII':                        True,
        'JSON_SORT_KEYS':                       True,
        'JSONIFY_PRETTYPRINT_REGULAR':          True,
        'JSONIFY_MIMETYPE':                     'application/json',
        'TEMPLATES_AUTO_RELOAD':                None,
    }
Flask配置文件

Session

当请求刚到来时,flask读取cookie中session对应的值,将加密的值解密反序列化成字典,放到视图函数。

当请求结束,flask会读取内存中session的值并放到浏览器的cookie中

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

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

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

闪现Flash

from flask import Flask,flash,get_flashed_messages
@app.route('/page1')
def page1():
    flash('临时数据存储','error')
    flash('sdfsdf234234','error')
    flash('adasdfasdf','info')
    return "Session"
@app.route('/page2')
def page2():
    print(get_flashed_messages(category_filter=['error']))  根据分类取数据
    return "Session" 

只存在于相邻请求之间,第一次请求赋值,第二期请求获取值,第三次闪现内容不会出现

中间件

call方法什么时候出发?
    - 用户发起请求时,才执行。
任务:在执行call方法之前,做一个操作,call方法执行之后做一个操作。
    class Middleware(object):
        def __init__(self,old):
            self.old = old

        def __call__(self, *args, **kwargs):
            ret = self.old(*args, **kwargs)
            return ret


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

 

 

 

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
    return 'Hello World!'
class Md(object):
    def __init__(self,old_wsgi_app):
        self.old_wsgi_app = old_wsgi_app
    def __call__(self,  environ, start_response):
        print('开始之前')
        # 。。。一些自定义操作
        ret = self.old_wsgi_app(environ, start_response)
        # 。。。一些自定义操作
        print('结束之后')
        return ret
if __name__ == '__main__':
    # 封装旧的app.wsgi_app,这是app.run()的原理,看源码。会调用__call__方法
    app.wsgi_app = Md(app.wsgi_app)
    app.run()

 

 flask中间件,在请求之前和之后分别进行操作 

 

特殊装饰器

@before_request  (自上而下)

before_request中如果有返回值,那么页面上将会返回before_request返回值,不在往下执行before_request和视图函数,倒序执行after_request

#在执行视图函数之前,requset都要经过(before_request)

@app.before_first_request

@after_request(response)     (自下往上执行)

@template_global

见模板

@template_filter

见模板

@errorhandler

出现错误时,自定制返回的内容

@app.errorhandler(404)
def not_found(arg):
  #arg 错误信息
    print(arg)
    return "没找到"

 蓝图给开发者提供目录结构

1.创建与项目名相同的文件夹

2.在该文件下创建__init__.py

3.在与文件同一级的目录下创建manage.py

4.创建该项目的静态文件和模板

.蓝图的关系的创建

manage.py中

from crm import create_app

app = create_app()

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

 __init__.py

from flask import Flask
from .views.account import ac
from .views.user import uc

def create_app():
    app = Flask(__name__)
    # @app.before_request
    # def x1():
    #     print('app.before_request')
    app.register_blueprint(ac)
    app.register_blueprint(uc,url_prefix='/api')
    return app

 account.py

from flask import Blueprint,render_template

ac = Blueprint('ac',__name__)

@ac.before_request
def x1():
    print('app.before_request')


@ac.route('/login')
def login():
    return render_template('login.html')


@ac.route('/logout')
def logout():
    return 'Logout'

 user.py

from flask import Blueprint

uc = Blueprint('uc',__name__)


@uc.route('/list')
def list():
    return 'List'


@uc.route('/detail')
def detail():
    return 'detail'

 

  •  在__init__.py 里面加上@before_request 方法把所有的请求都会经过
  • 在每一个蓝图加上@before_request 那么就意味着只有该蓝驱的所有请求经过

threading.local

为每一个线程开辟独立空间

获取一个线程的唯一标识,  threading.get_ident()

获取携程的唯一标识,greenlet.getcurrent()

threading.local【和flask无任何关系】
        作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。
            import threading
            from threading import local
            import time

            obj = local()


            def task(i):
                obj.xxxxx = i
                time.sleep(2)
                print(obj.xxxxx,i)

            for i in range(10):
                t = threading.Thread(target=task,args=(i,))
                t.start()

        问题:
            - 如何获取一个线程的唯一标记? threading.get_ident()
            - 根据字典自定义一个类似于threading.local功能?
                import time
                import threading

                DIC = {}

                def task(i):
                    ident = threading.get_ident()
                    if ident in DIC:
                        DIC[ident]['xxxxx'] = i
                    else:
                        DIC[ident] = {'xxxxx':i }
                    time.sleep(2)

                    print(DIC[ident]['xxxxx'],i)

                for i in range(10):
                    t = threading.Thread(target=task,args=(i,))
                    t.start()
                
            - 根据字典自定义一个为每个协程开辟空间进行存取数据。
            
                import time
                import threading
                import greenlet

                DIC = {}

                def task(i):
                    
                    # ident = threading.get_ident()
                    ident = greenlet.getcurrent()
                    if ident in DIC:
                        DIC[ident]['xxxxx'] = i
                    else:
                        DIC[ident] = {'xxxxx':i }
                    time.sleep(2)

                    print(DIC[ident]['xxxxx'],i)

                for i in range(10):
                    t = threading.Thread(target=task,args=(i,))
                    t.start()
            
            - 通过getattr/setattr 构造出来 threading.local的加强版(协程)
                import time
                import threading
                try:
                    import greenlet
                    get_ident =  greenlet.getcurrent
                except Exception as e:
                    get_ident = threading.get_ident

                class Local(object):
                    DIC = {}

                    def __getattr__(self, item):
                        ident = get_ident()
                        if ident in self.DIC:
                            return self.DIC[ident].get(item)
                        return None

                    def __setattr__(self, key, value):
                        ident = get_ident()
                        if ident in self.DIC:
                            self.DIC[ident][key] = value
                        else:
                            self.DIC[ident] = {key:value}
                        

                obj = Local()

                def task(i):
                    obj.xxxxx = i
                    time.sleep(2)
                    print(obj.xxxxx,i)

                for i in range(10):
                    t = threading.Thread(target=task,args=(i,))
                    t.start()
            
threading.local为每一个线程开辟独立空间

上下文管理

上下文管理(第一次)
        请求到来时候:
            # ctx = RequestContext(self, environ) # self是app对象,environ请求相关的原始数据
            # ctx.request = Request(environ)
            # ctx.session = None
            
            # 将包含了request/session的ctx对象放到“空调”
                {
                    1232:{ctx:ctx对象}
                    1231:{ctx:ctx对象}
                    1211:{ctx:ctx对象}
                    1111:{ctx:ctx对象}
                    1261:{ctx:ctx对象}
                }
                
        视图函数:
            from flask import reuqest,session 
            
            request.method 
            
            
        请求结束:
            根据当前线程的唯一标记,将“空调”上的数据移除。
上下文管理(第一次)

 

Session+Flask实现用户登录

from flask import Flask,render_template,request,session,redirect

app=Flask(__name__)

#session 如果需要用到session 需要加盐.
# 本质上他是放在cookies里,并不是像django一样放在数据库
app.secret_key ='213fdasfa123df'

@app.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')
    if user=='ming' and pwd=='123':
        session['user_info']={'username':user}
        return redirect('/index')

    return render_template('login.html',error='用户名或密码错误')
    # return render_template('login.html',**{'error':'用户名或者密码错误'})


@app.route('/index')
def index():
    user_info=session.get('user_info')
    if user_info:
        return render_template('index.html')
    return redirect('/login')

if __name__ == '__main__':
    app.run()
Session+Flask实现用户登录
posted @ 2019-03-03 21:23  离人怎挽_wdj  阅读(138)  评论(0编辑  收藏  举报