flask- 偏函数、请求上下文、信号、flask-session保存redis中
local
from threading import get_ident,Thread
使用thread local对象可以基于线程存储全局变量,但在web引用中出现两个问题:
1、有些应用使用的greenlet协程,无法保证数据隔离的问题,因为不同协程在同一个线程中;
2.、无法保证每个http请求使用的都是不同的线程,这样存储thread local的数据可能是之前残留的
所以werkzeug开发自己local对象,解决上述问题
即通过线程id(或协程id)来分别存储数据。
偏函数:
调用:import:from functools import partial
定义一个偏函数,调用偏函数,如果原函数传参数,永远函数的参数,缺值可用偏函数参数
def add(a, b=2): return a + b def add2(a=2, b=3): return a + b if __name__ == "__main__": mysum = partial(add, 10) print mysum() # 也可根据关键字预先设定的参数值 mysum2 = partial(add, b=3) print mysum2(1) # 如果没有关键字,按原有参数顺序补充 mysum3 = partial(add2, 1) print mysum3() # 结果 12 4 ———————————————— 版权声明:本文为CSDN博主「HQ_JSY」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/JSYhq/article/details/88633426
请求上下文
1 app.__call__ 2 wsgi_app(environ, start_response) 2.1 ctx = self.request_context(environ) 2.1.1 return RequestContext(self, environ) 这里的self是app,environ请求相关 2.1.2 return RequestContext(self, environ) 得到了RequestContext的对象,而且有request属性 2.2 2.1中的ctx就是RequestContext的对象 2.3 ctx.push()执行这个,就是RequestContext的对象的push方法 2.3.1 #执行这个,self-->ctx _request_ctx_stack.push(self) 2.3.1.1 我们发现_request_ctx_stack = LocalStack() 他的push方法的源码: def push(self, obj): rv = getattr(self._local, "stack", None) if rv is None: # self._local=>stack-->storage['线程id']['stack']=[ctx,] self._local.stack = rv = [] rv.append(obj) return rv 3在请求中获取request.form 3.1 request是LocalProxy的对象,当获取属性的时候会走__getattr__ def __getattr__(self, name): if name == "__members__": return dir(self._get_current_object()) #name-->form, #self._get_current_object()===>ctx.request,form #_get_current_object()---》self.__local() return getattr(self._get_current_object(), name) 3.1.1 self._get_current_object():源码:最终:partial(_lookup_req_object, "request") def _get_current_object(self): if not hasattr(self.__local, "__release_local__"): #local==>partial(_lookup_req_object, "request") #def __init__(self, local, name=None): # object.__setattr__(self, "_LocalProxy__local", local) #self.__local()===>local() return self.__local() try: return getattr(self.__local, self.__name__) except AttributeError: raise RuntimeError("no object bound to %s" % self.__name__) 4 partial(_lookup_req_object, "request")偏函数的源码 def _lookup_req_object(name): #name是request #ctx top = _request_ctx_stack.top if top is None: raise RuntimeError(_request_ctx_err_msg) #ctx-->request return getattr(top, name) 4.1中_request_ctx_stack.top @property def top(self): try: return self._local.stack[-1] except (AttributeError, IndexError): return None
g对象:
当前请求内设置便可以取值,必须先设置后取值,当前请求可以取无限次(其他请求取不到)
from flask import Flask, g, render_template, request from ulits import login_log app = Flask(__name__) @app.route('/') def hello_world(): return 'index' @app.route('/login/', methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template('login.html') else: username = request.form.get('username') password = request.form.get('password') if username == 'zhiliao' and password == '111111': g.username = username login_log() return '恭喜您!登录成功' else: return '登录名或密码错误!' if __name__ == '__main__': app.run(debug=True, host='127.0.0.1', port=8081)
from flask import g def login_log(): print('登录名为: {}'.format(g.username))
信号:
往信号中注册函数,无序调用,因为flask已经给我们设置了调用点
1 template_rendered = _signals.signal('template-rendered') # 模板渲染后执行 2 before_render_template = _signals.signal('before-render-template') # 模板渲染前执行 3 request_started = _signals.signal('request-started') # 请求到来前执行 4 request_finished = _signals.signal('request-finished') # 请求结束后执行 5 request_tearing_down = _signals.signal('request-tearing-down') # 请求执行完毕后自动执行(无论成功与否) 6 got_request_exception = _signals.signal('got-request-exception') # 请求执行出现异常时执行 7 appcontext_tearing_down = _signals.signal('appcontext-tearing-down') # 应用上下文执行完毕后自动执行(无论成功与否) 8 appcontext_pushed = _signals.signal('appcontext-pushed') # 应用上下文push时执行 9 appcontext_popped = _signals.signal('appcontext-popped') # 应用上下文pop时执行 10 message_flashed = _signals.signal('message-flashed') # 调用flash在其中添加数据时,自动触发
与信号绑定:signals.request_started.connect(func)
触发信号:signals.request_started.send()
自定义信号:
xxxxx = _signals.signal('xxxxx')
from flask import Flask from flask.signals import _signals app = Flask(import_name=__name__) # 自定义信号 xxxxx = _signals.signal('xxxxx') def func(sender,a): print(sender,a) print("我是自定义信号") # 自定义信号中注册函数 xxxxx.connect(func) @app.route("/x") def index(): # 触发信号 xxxxx.send("sb",a="1") return 'Index' if __name__ == '__main__': app.run()
flask-session保存到redis中
1、基础方法
安装pip3 install flask-session
from flask import Flask,session from flask_session import RedisSessionInterface import redis app = Flask(__name__) app.secret_key="ajksda" conn=redis.Redis(host='127.0.0.1',port=6379) #use_signer是否对key签名 app.session_interface=RedisSessionInterface(conn,key_prefix='jason',use_signer=True, permanent=False) @app.route('/') def hello_world(): session['sb']='jason' return 'Hello World!' @app.route("/index") def index(): print(session['sb']) return "ok" if __name__ == '__main__': app.run()
key_prefix='前缀':拼接session的前缀
use_signer=True:是否对key签名(即app.sercet_key不需要设置)
permanent=False:True关闭再开浏览器,值还在
2、常用方法
from flask import Flask,session import redis from flask_session import Session app = Flask(__name__) app.config['SESSION_TYPE'] = 'redis' app.config['SESSION_REDIS'] =redis.Redis(host='127.0.0.1',port='6379') app.config['SESSION_KEY_PREFIX']="jason" Session(app) @app.route('/') def hello_world(): session['sb']='jason' return 'Hello World!' @app.route("/index") def index(): print(session['sb']) return "ok" if __name__ == '__main__': app.run()
调用from flask_session import Session
看Session源码,可以了解1、拼接session前缀,2、数据库指定等都可以自定义
原文地址:https://www.cnblogs.com/xiaowangba9494/p/11862745.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php提供实现反射的方法和实例代码
- PHP实现批量修改文件名的方法示例
- Linux VPS快速下载Bilibili视频脚本 ,支持1080P/720P/360P等格式
- PHP递归统计系统中代码行数
- PHP切割整数工具类似微信红包金额分配的思路详解
- php写入文件不覆盖的实例讲解
- php解决crontab定时任务不能写入文件问题的方法分析
- Laravel项目中timeAgo字段语言转换的改善方法示例
- php生成微信红包数组的方法
- 解决php写入数据库乱码的问题
- php写入txt乱码的解决方法
- PHP实现的AES 128位加密算法示例
- php写入mysql中文乱码的实例解决方法
- php实现的支付宝网页支付功能示例【基于TP5框架】
- php校验公钥是否可用的实例方法