Django 缓存、信号
Reference: http://www.cnblogs.com/lianzhilei/p/6365877.html
缓存
由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回
Django中提供了6种缓存方式:
- 开发调试
- 内存
- 文件
- 数据库
- Memcache缓存(python-memcached模块、pylibmc模块)
1、配置
① 开发配置
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
# 此为开始调试用,实际内部不做任何操作 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎 'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期) 'OPTIONS':{ 'MAX_ENTRIES': 300, # 最大缓存个数(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) }, 'KEY_PREFIX': '', # 缓存key的前缀(默认空) 'VERSION': 1, # 缓存key的版本(默认1) 'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】) } } # 自定义key def default_key_func(key, key_prefix, version): """ Default function to generate keys. Constructs the key used by all other methods. By default it prepends the `key_prefix'. KEY_FUNCTION can be used to specify an alternate function with custom key making behavior. """ return '%s:%s:%s' % (key_prefix, version, key) def get_key_func(key_func): """ Function to decide which key function to use. Defaults to ``default_key_func``. """ if key_func is not None: if callable(key_func): return key_func else: return import_string(key_func) return default_key_func
② 内存配置
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
# 此缓存将内容保存至内存的变量中 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'unique-snowflake', } } # 注:其他配置同开发调试版本
③ 文件配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
④ 数据库配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
⑤ Memcache缓存(python-memcached模块)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
⑥ Memcache缓存(pylibmc模块)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2、应用
① 全站使用
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存 MIDDLEWARE = [ # 写到最上面 'django.middleware.cache.UpdateCacheMiddleware', # 其他中间件... # 写到最下面 'django.middleware.cache.FetchFromCacheMiddleware', ]
② 单独视图缓存
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
方式一: from django.views.decorators.cache import cache_page @cache_page(60 * 15) def my_view(request): ... 方式二: from django.views.decorators.cache import cache_page urlpatterns = [ url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)), ]
③ 局部视图使用
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
a. 引入TemplateTag {% load cache %} b. 使用缓存 {% cache 5000 缓存key %} 缓存内容 {% endcache %}
3、单独视图缓存示例
cache方法处理的请求,都进行缓存10秒
HTML文件:
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> </body> </html>
配置文件:
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': os.path.join(BASE_DIR,'cache'), } }
处理文件:
1
2
3
4
5
6
|
from django.views.decorators.cache import cache_page @cache_page ( 10 ) # 装饰cache方法 def cache(request): import time ctime = time.time() return render(request, 'cache.html' ,{ 'ctime' :ctime}) |
4、局部视图示例
缓存html文件某一部分
HTML文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
配置文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
处理文件:
1
2
3
4
|
def cache(request): import time ctime = time.time() return render(request, 'cache.html' ,{ 'ctime' :ctime}) |
5、全局生效
配置文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
其余文件都一致,全局优先级大;请求流程-->使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,如果不存在则接着往下走,执行views函数,最后经过UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
信号
Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者
1、Django内置信号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
Model signals pre_init # django的modal执行其构造方法前,自动触发 post_init # django的modal执行其构造方法后,自动触发 pre_save # django的modal对象保存前,自动触发 post_save # django的modal对象保存后,自动触发 pre_delete # django的modal对象删除前,自动触发 post_delete # django的modal对象删除后,自动触发 m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发 class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发 Management signals pre_migrate # 执行migrate命令前,自动触发 post_migrate # 执行migrate命令后,自动触发 Request / response signals request_started # 请求到来前,自动触发 request_finished # 请求结束后,自动触发 got_request_exception # 请求异常后,自动触发 Test signals setting_changed # 使用test测试修改配置文件时,自动触发 template_rendered # 使用test测试渲染模板时,自动触发 Database Wrappers connection_created # 创建数据库连接时,自动触发 |
内置信号调用方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2、内置信号注册函数
对于内置的信号,使用时需要在信号中注册执行函数,当程序执行相应操作时,自动触发注册函数:
创建文件sg.py并注册函数:
1
2
3
4
5
6
7
8
9
|
# sg.py from django.db.models.signals import pre_init def f1(sender, * * kwargs): print ( "构造方法执行前" ) print (sender, kwargs) pre_init.connect(f1) # django的modal执行其构造方法前,自动触发 可以为内置信号中的任意 |
__init__.py加载文件sg.py:
1
|
import sg |
处理文件views.py:
1
2
3
4
5
6
7
8
9
|
from app01 import models def signal(request): obj1 = models.UserInfo.objects.create(user = "root" ) print ( 'obj1' ) obj2 = models.UserInfo.objects.create(user = "root" ) print ( 'obj2' ) return HttpResponse( "OK" ) |
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
3、自定义信号
定义信号:
1
2
3
|
import django.dispatch pizza_done = django.dispatch.Signal(providing_args = [ "toppings" , "size" ]) # toppings,size 需要传入的参数 |
注册信号:
1
2
3
4
5
|
def callback(sender, * * kwargs): print ( "callback" ) print (sender,kwargs) pizza_done.connect(callback) |
触发信号:
1
2
3
|
from 路径 import pizza_done pizza_done.send(sender = 'seven' ,toppings = 123 , size = 456 ) |
由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发