Flask-Caching
Flask-Caching 是 Flask 的一个扩展,它为 Flask 应用提供了缓存支持。缓存是一种优化技术,可以存储那些费时且不经常改变的运算结果,从而加快应用的响应速度。
一、初始化配置
安装 Flask-Caching 扩展:
pip3 install Flask-Caching
配置说明:
CACHE_TYPE
: 指定缓存类型。可以是 “null”(无缓存)、“simple”(简单缓存)、“redis”、“memcached” 等。简单缓存(SimpleCache)是内存中的缓存,不需要额外的缓存服务器。CACHE_DEFAULT_TIMEOUT
: 缓存项的默认过期时间(秒)。
示例代码:
from flask import Flask
from flask_caching import Cache
config = {
"DEBUG": True, # Flask 的调试模式
"CACHE_TYPE": "SimpleCache", # 使用简单缓存
"CACHE_DEFAULT_TIMEOUT": 300 # 缓存默认超时时间(5分钟)
}
app = Flask(__name__)
app.config.from_mapping(config)
cache = Cache(app) # 初始化缓存对象
二、使用缓存
在路由中,可以使用 cache.set
方法来设置一个缓存项,使用 cache.get
方法来获取缓存项。
设置缓存:
@app.route('/')
def index():
cache.set('name', 'bruce') # 设置缓存项
return 'index'
获取缓存:
@app.route('/get')
def get():
res = cache.get('name') # 获取缓存项
return res if res else 'Not cached'
注意:cache.get
方法在缓存项不存在或已过期时将返回 None
,所以在返回结果时你可能需要检查它是否为 None
。
三、缓存到 Redis
如果想使用 Redis 作为缓存后端,你需要安装 Redis 服务器和 redis
Python 包,并更改 CACHE_TYPE
配置:
pip3 install redis
然后,配置 Flask 应用使用 Redis:
config = {
"CACHE_TYPE": "RedisCache", # 使用 Redis 缓存
# 配置 Redis 服务器地址和端口
"CACHE_REDIS_URL": "redis://localhost:6379/0"
# 其他 Redis 相关配置...
}
使用 Flask-Caching 可以显著提高应用的性能,特别是在处理那些计算密集型或数据库密集型的请求时。不过,需要注意合理配置缓存的过期时间,以避免缓存的数据过时。
Flask信号
一、简单介绍
信号的概念
- 信号 是一种松耦合的通信方式,允许对象间的交互而不需要显式调用对方的方法。
- 在 Flask 和 Django 中,信号可以用于监听和响应框架的特定事件,如请求开始、模板渲染、模型保存等。
信号与信号量的区别
- 信号(Signal)是观察者模式的一种实现,用于事件通知和通信。
- 信号量(Semaphore)是并发编程中用于控制对共享资源访问的计数器锁。
信号的好处
- 低侵入性:信号允许在不修改现有代码的基础上,添加新的功能或行为。
- 解耦:信号可以降低代码间的依赖关系,提高模块化。
面向切面编程(AOP)
- 这种编程范式允许开发者定义跨多个对象的横切关注点(cross-cutting concerns),如日志、事务管理等。信号可以看作是AOP的一种实现方式。
信号与请求扩展的关系
- 信号可以完成之前在请求扩展中完成的事情。
- 它们的机制不同:请求扩展通常通过装饰器或中间件来修改请求处理流程,而信号则是在特定事件发生时触发。
- 信号更为丰富,可以在更多的事件点进行操作。
二、内置信号的使用
1.Flask内置信号
request_started
:在请求到来前执行。request_finished
:在请求结束后执行。before_render_template
:在模板渲染前执行。template_rendered
:在模板渲染后执行。got_request_exception
:在请求执行出现异常时执行。request_tearing_down
:在请求执行完毕后自动执行(无论成功与否)。appcontext_tearing_down
:在应用上下文执行完毕后自动执行(无论成功与否)。appcontext_pushed
:在应用上下文push时执行。appcontext_popped
:在应用上下文pop时执行。message_flashed
:当调用flask.flash
在其中添加数据时,自动触发。
2.简单使用
以下是使用before_render_template
信号的示例:
-
编写一个响应信号的函数:这个函数会在信号被触发时执行。
def func1(*args, **kwargs): print('模板渲染了') print(args) print(kwargs.get('template').name) if 'index.html' == kwargs.get('template').name: print('记日志了')
这个函数接收任意数量的位置参数和关键字参数,并检查模板的名称。如果模板是
index.html
,它将打印一条日志消息。 -
将函数绑定到信号:使用
connect
方法将函数绑定到before_render_template
信号。from flask import signals signals.before_render_template.connect(func1)
这样,每当模板渲染之前,
func1
都会被调用。 -
等待信号触发:通过正常的路由和模板渲染流程,信号会被自动触发。
@app.route('/<string:name>') def index(name): return render_template('index.html', name=name) @app.route('/login') def login(): return render_template('login.html')
当访问
/
或/login
路径时,对应的模板将被渲染,并且在渲染之前,func1
会被调用。
三、flask自定义信号
1.自定义信号的步骤
- 自定义信号:使用
flask.signals._signals.signal
来创建一个新的信号。 - 编写响应函数:这个函数会在信号被触发时执行。
- 将函数绑定到自定义信号:使用
connect
方法将函数绑定到你的自定义信号上。 - 手动触发信号:在应用程序逻辑中,当满足特定条件时,手动发送(触发)信号。
2.示例
from flask import Flask, request from flask.signals import _signals app = Flask(__name__) app.debug = True # 定义一个自定义信号 create_user_signal = _signals.signal('create_user') # 修改信号名称以避免混淆 # 编写回调函数,当自定义信号触发时执行 def func1(*args, **kwargs): print('自定义信号执行了', kwargs) # 将回调函数绑定到自定义信号 create_user_signal.connect(func1) def create_user_handler(sql, name): # 触发自定义信号,传递额外的参数 create_user_signal.send(name=name) # 使用正确的信号对象来发送信号 # 数据库操作... print(sql % name) @app.route('/create_user/<name>') def create_user(name): print('创建用户', name) sql = 'insert into user (name) values (%s)' create_user_handler(sql, name) return f'创建用户{name} 成功' if __name__ == '__main__': app.run()
四、Django中的信号
1.内置信号
- Model signals:与模型操作相关的信号。
pre_init
:在模型实例初始化之前触发。post_init
:在模型实例初始化之后触发。pre_save
:在模型实例保存之前触发。post_save
:在模型实例保存之后触发。pre_delete
:在模型实例删除之前触发。post_delete
:在模型实例删除之后触发。m2m_changed
:在多对多字段改变时触发。class_prepared
:在应用启动时,模型类准备好后触发。
- Management signals:与数据库迁移相关的信号。
pre_migrate
:在执行迁移命令之前触发。post_migrate
:在执行迁移命令之后触发。
- Request/response signals:与请求和响应相关的信号。
request_started
:在请求开始时触发。request_finished
:在请求结束时触发。got_request_exception
:在请求处理中出现异常时触发。
- Test signals:与测试相关的信号。
setting_changed
:在测试中修改设置时触发。template_rendered
:在测试中渲染模板时触发。
- Database Wrappers:
connection_created
:在创建数据库连接时触发。
2.信号的使用
- 写一个函数
from django.db.models.signals import pre_save
import logging
def callBack(sender, **kwargs):
# 这里可以添加逻辑,例如过滤特定的表
print('对象保存了')
# 可以在这里执行异步任务,比如使用 Celery
-
绑定信号
-
方法一:直接使用
connect
方法。 -
pre_save.connect(callBack)
-
方法二:使用装饰器
@receiver
。 -
from django.dispatch import receiver @receiver(pre_save) def my_callback(sender, **kwargs): print("对象创建成功") print(sender) print(kwargs)
-
3. 自定义信号
-
定义信号:使用
django.dispatch.Signal
创建一个新的信号。 -
编写回调函数:创建一个函数来响应信号。
-
连接信号:使用信号的
connect
方法将回调函数与信号连接。 -
触发信号:在适当的位置使用信号的
send
方法来手动触发信号。 -
示例
-
import django.dispatch # 定义信号 pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) # 编写回调函数 def callback(sender, **kwargs): print("Pizza is ready!") print(sender, kwargs) # 连接信号 pizza_done.connect(callback) # 触发信号 pizza_done.send(sender='seven', toppings='pepperoni', size='large')
-