请求上下文、g对象、flask_session、信号、自定义命名

flask之请求上下文、g对象、flask_session、信号、自定义命名

1、local与偏函数

1、local内部实现原理

import time
from threading import Thread,local,get_ident

#####这是使用local对象
# a = local()
# #
# # def task(arg):
# #     a.value = arg
# #
# #     time.sleep(1)
# #
# #     print(a.value)

#####用函数的形式来模拟local
# storage = {}
# def set(k,v):
#     # 获取线程id
#     ident = get_ident()
#     if ident in storage:
#         storage[ident][k]=v
#     else:
#         storage[ident] = {k:v}
#
# def get(k):
#     ident = get_ident()
#     return storage[ident][k]
#
# def task(arg):
#     set('val',arg)
#     time.sleep(1)
#     v = get("val")
#     print(v)


#面向对象版1

# class Local:
#     storage ={}
#     def set(self,k,v):
#         ident = get_ident()
#         if ident in Local.storage:
#             Local.storage[ident][k] = v
#         else:
#             Local.storage[ident] = {k:v}
#
#     def get(self,k):
#         ident = get_ident()
#         return Local.storage[ident][k]
#
# obj = Local()
# def task(arg):
#     obj.set("val",arg)
#     time.sleep(1)
#     v = obj.get("val")
#     print(v)

# #面向对象的setattr,getattr版
# class Local:
#     storage ={}
#     def __setattr__(self,k,v):
#         ident = get_ident()
#         if ident in Local.storage:
#             Local.storage[ident][k] = v
#         else:
#             Local.storage[ident] = {k:v}
#
#     def __getattr__(self,k):
#         ident = get_ident()
#         return Local.storage[ident][k]

# obj = Local()
# # def task(arg):
# #     obj.val=arg
# #     time.sleep(1)
# #     print(obj.val)

# 面向对象,将storage变成对象的属性
class Local(object):
    def __init__(self):
        #防止getattr递归
        object.__setattr__(self,"storage",{})
        #self.storage = {}
    def __setattr__(self,k,v):
        ident = get_ident()
        if ident in self.storage:
            self.storage[ident][k] = v
        else:
            self.storage[ident] = {k:v}

    def __getattr__(self,k):
        ident = get_ident()
        return self.storage[ident][k]


obj = Local()
def task(arg):
    obj.val=arg
    time.sleep(1)
    print(obj.val)

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

2、偏函数

第一个参数是函数的对象,第二个到后面都是函数的参数,严格按照python函数的传参规则

#偏函数partial
from functools import partial

def fun(a,b,c,d):

    return a+b+c+d

#第一个参数是函数的对象,第二个到后面都是函数的参数,严格按照python函数的传参规则
tes = partial(fun,a=1,b=2)
tes1 = partial(tes,c=3)
print(tes) # 得到partial对象
print(tes1(d=4)) # 10

2、请求上下文实现原理

3、g对象

g对象是global是当前请求的全局设置变量,其他的请求时无法得到的,专门用来存储用户信息的g对象

我们不用request请求来设置因为request中有很多属性,防止设置的属性与request属性冲突改变了request中的属性

一般用g对象在before_request中设置属性给当次请求的响应函数来使用

#g ,global,当前请求的全局,
#g,对象只当前请求内有效,一旦不是一个请求,就不能获取
from flask import Flask,g,request

app = Flask(__name__)

@app.before_request
def befor():
    #你知道request里面有哪些?
    #g 它就怕你和全局request改变了它里面的属性
    # 一般在before_request中使用携带参数给视图函数
    g.name = "tank"

@app.route("/")
def index():

    print(g.name)
    return "ok"

@app.route("/index")
def index1():
    #print(g.name) # 根路径下获取了,此处无法获取
    return "ok1"

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

4、flask_session

将默认保存的签名cookie中的值 保存到 redis/memcached/file/Mongodb/SQLAlchemy

1、下载模块 

pip install flask-session

2、从flask_session中导入要存的数据库

from flask_session import RedisSessionInterface
from flask import Flask,session
from flask_session import RedisSessionInterface
import redis
app = Flask(__name__)
conn=redis.Redis(host='127.0.0.1',port=6379, password=2694)
app.secret_key = "123"
#permanent=True,如果这个值为True,表示关闭浏览器,不失效,如果为Fasle,表示关闭浏览器,session就失效
app.session_interface=RedisSessionInterface(conn,key_prefix='lqz',use_signer=True)

@app.route('/')
def hello_world():
    session['name']='lqz'
    return 'Hello World!'

@app.route("/index")
def index():
    print(session['name'])
    return "ok"

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

3、一般用法是在app中配置数据库后直接导入Session

from redis import Redis
from flask import Flask,session
from flask_session import Session
app = Flask(__name__)

app.config['SESSION_TYPE'] = 'redis'

app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379', password='2694')

Session(app)

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

@app.route("/index")
def index1():
    print(session['name'])
    return "ok"

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

5、信号

1、下载模块

pip install blinker

2、设置触发信号的执行函数

3、设置信号触发点

request_started = _signals.signal('request-started')                # 请求到来前执行
request_finished = _signals.signal('request-finished')              # 请求结束后执行
 
before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行
 
got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
 
request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 应用上下文执行完毕后自动执行(无论成功与否)
 
appcontext_pushed = _signals.signal('appcontext-pushed')            # 应用上下文push时执行
appcontext_popped = _signals.signal('appcontext-popped')            # 应用上下文pop时执行
message_flashed = _signals.signal('message-flashed')                # 调用flask在其中添加数据时,自动触发

使用:

from flask import Flask,signals

app = Flask(__name__)

#触发信号要执行函数
def si(*args,**kwargs):
    print("触发这个信号",args,kwargs)

# 触发信号点
signals.request_started.connect(si)

@app.route("/")
def index():
    return "123"

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

自定义信号(了解)

from flask import Flask
from flask.signals import _signals

app = Flask(__name__)

# 自定义信号
xxxxx = _signals.signal('xxxxx')


# 接收参数的时候,就算send方法不传,也要接收一个参数,后面按照关键字接收参数
def func(arg,on1):
    print("123123",arg,on1)


# 自定义信号中注册函数
xxxxx.connect(func)


@app.route("/x")
def index():
    # 触发信号 #传参的时候,一个必须是位置参数,后面的产生必须是关键字参数
    xxxxx.send("sb",on1="sb2")
    return 'Index'


if __name__ == '__main__':

    app.run()

6、自定义命令 flask-script

用于实现类似于django中 python3 manage.py runserver ...类似的命令

1、下载模块

pip install flask-script

2、使用

from flask_script import Manager
app = Flask(__name__)
manager=Manager(app)
...
if __name__ == '__main__':
    manager.run()
#以后在执行,直接:python3 manage.py runserver
#python3 manage.py runserver --help
@manager.command
def custom(arg):
    """
    自定义命令
    python manage.py custom 123
    :param arg:
    :return:
    """
    print(arg)


@manager.option('-n', '--name', dest='name')
#@manager.option('-u', '--url', dest='url')
def cmd(name, url):
    """
    自定义命令(-n也可以写成--name)
    执行: python manage.py  cmd -n lqz -u http://www.oldboyedu.com
    执行: python manage.py  cmd --name lqz --url http://www.oldboyedu.com
    :param name:
    :param url:
    :return:
    """
    print(name, url)
自定义命令

 

posted @ 2020-03-20 23:54  Mr沈  阅读(203)  评论(0编辑  收藏  举报