请求上下文、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)