Django入门到放弃之缓存及信号机制
在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面.
当一个网站的用户访问量很大的时候,每一次的的后台操作,都会消耗很多的服务端资源,所以必须使用缓存来减轻后端服务器的压力.
缓存是将一些常用的数据保存内存或者memcache中,在一定的时间内有人来访问这些数据时,则不再去执行数据库及渲染等操作,而是直接从内存或memcache的缓存中去取得数据,然后返回给用户.
- 开发调试缓存
- 内存缓存
- 文件缓存
- 数据库缓存
- Memcache缓存(使用python-memcached模块)
- Memcache缓存(使用pylibmc模块)
经常使用的有文件缓存和Mencache缓存
Django提供了不同粒度的缓存,可以缓存某个页面,可以只缓存一个页面的某个部分,甚至可以缓存整个网站.
三种粒度:整站缓存,单页面缓存,局部缓存
----------------------------------------------------------------------------------------------
单页面缓存
# index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>你好,世界</h1>
当前时间是:{{ ctime }}
</body>
</html>
# urls.py
from app01 import views
urlpatterns = [
path('index/', views.index),
]
# settings.py
# 新增以下配置
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', #指定缓存使用的引擎
# 'LOCATION': '/var/tmp/django_cache', #指定缓存的路径
'LOCATION': r'D:\cache', #指定缓存的路径
'TIMEOUT':300, #缓存超时时间(默认为300秒,None表示永不过期)
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认剔除1/3过期)
}
}
}
# views.py
from django.shortcuts import render
from django.views.decorators.cache import cache_page
# Create your views here.
@cache_page(5)
def index(request):
import time
ctime = time.time()
return render(request,'index.html',context={'ctime':ctime})
----------------------------------------------------------------------------------------------
局部缓存
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>你好,世界</h1>
当前时间是:{{ ctime }}
<hr>
这里使用局部缓存:
{% load cache %}
<!-- 3表示缓存时间 current_time表示局部缓存的名称 -->
{% cache 3 'current_time' %}
当前时间是:{{ ctime }}
{% endcache %}
</body>
</html>
----------------------------------------------------------------------------------------------
缓存整个站点,是最简单的缓存方法
在 MIDDLEWARE_CLASSES 中加入 “update” 和 “fetch” 中间件
MIDDLEWARE_CLASSES = (
‘django.middleware.cache.UpdateCacheMiddleware’, #第一,重写了process_response
'django.middleware.common.CommonMiddleware',
‘django.middleware.cache.FetchFromCacheMiddleware’, #最后,重写了process_requset
)
“update” 必须配置在第一个
“fetch” 必须配置在最后一个
CACHE_MIDDLEWARE_SECONDS=5 #5表示缓存的时间 单位秒
# views.py
from rest_framework.views import APIView
from app01 import serializer
from app01 import models
from django.core.cache import cache
from rest_framework.response import Response
class Book(APIView):
def get(self, request):
res_data = cache.get('book_list_dic')
if res_data: #如果缓存存在则直接返回
print('走了缓存')
return Response(res_data)
else:
book_list = models.Book.objects.all()
ser = serializer.BookSer(book_list, many=True)
# 如果换成没有则添加 10表示缓存的时间
cache.set('book_list_dic',ser.data,10)
print('没有走缓存')
return Response(ser.data)
# serializer.py
from app01 import models
from rest_framework import serializers
class BookSer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
# models.py
from django.db import models
# Create your models here.
class Book(models.Model):
# 由于继承了BaseModel,is_delete和create_time字段自动生成
name = models.CharField(max_length=16)
price = models.DecimalField(max_digits=5, decimal_places=2)
1 Django提供一种信号机制。当发生一些动作的时候,发出信号,然后监听了这个信号的函数就会执行
2 Django内置信号
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 # 创建数据库连接时,自动触发
3 内置信号的使用(两种方式)
# #1 导入内置信号
# from django.core.signals import request_started
# #2 写一个函数
# def aa(sender, **kwargs):
# print(sender)
# print(kwargs)
# print('请求来了,我写日志了。。。')
#
#
# #3 跟内置信号绑定
# request_started.connect(aa)
# 方式二
from django.core.signals import request_started,request_finished
from django.dispatch import receiver
@receiver(request_finished) # 内置信号pre_save和my_callback函数绑定了
def my_callback(sender, **kwargs):
print("请zzou了,走了我")
4 信号的应用场景:
-记录日志(对象创建就写入日志)
-解耦合
"一劳永逸" 的话,有是有的,而 "一劳永逸" 的事却极少