缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存
视图渲染有一定成本,对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数
案例分析
from django.shortcuts import render
def index(request):
# 时间复杂度极高的渲染
book_list = Book.objects.all() #-> 此处假设耗时2s
return render(request, 'index.html', locals())
优化思想
given a URL, try finding that page in the cache
if the page is in the cache:
return the cached page
else:
generate the page
save the generated page in the cache (for next time)
return the generated page
1,博客列表页
2,电商商品详情页
3,缓存导航及页脚
Django中提供多种缓存方式,如需使用需要在settings.py中进行配置
1,数据库缓存
Django可以将其缓存的数据存储在您的数据库中
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
'TIMEOUT': 300, #缓存保存时间 单位秒,默认值为300,
'OPTIONS':{
'MAX_ENTRIES': 300, #缓存最大数据条数
'CULL_FREQUENCY': 2,#缓存条数达到最大值时 删除1/x的缓存数据
}
}
}
创建缓存表
python manage.py createcachetable
2,文件系统缓存
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',#这个是文件夹的路径
#'LOCATION': 'c:\test\cache',#windows下示例
}
}
3, 本地内存缓存
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake'
}
}
在视图View中使用cache
from django.views.decorators.cache import cache_page
@cache_page(30) -> 单位s
def my_view(request):
...
在路由中使用
from django.views.decorators.cache import cache_page
urlpatterns = [
path('foo/', cache_page(60)(my_view)),
]
在模板中使用
{
% load cache %}
{
% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{
% endcache %}
缓存api
作用:局部缓存部分结果
使用:
#指定配置引入
from django.core.cache import caches
cache1 = caches['myalias']
cache2 = caches['myalias_2']
#默认配置引入【指的配置中的default项】 等同于 caches['default']
from django.core.cache import cache
#常规命令 set
#key: 字符串类型
#value: Python对象
#timeout:缓存存储时间 默认值为settings.py CACHES对应配置的TIMEOUT
#返回值:True
cache.set('my_key', 'myvalue', 30)
#常规命令 get
#返回值:为key的具体值,如果没有数据,则返回None
cache.get('my_key')
#可添加默认值,如果没取到返回默认值
cache.get('my_key', 'default值')
#常规命令 add 只有在key不存在的时候 才能设置成功
#返回值 True or None
cache.add('my_key', 'value') #如果my_key已经存在,则此次赋值失效
#常规命令 get_or_set 如果未获取到数据 则执行set操作
#返回值 key的值
cache.get_or_set('my_key', 'value', 10)
#常规命令 get_many() set_many()
#返回值 set: None
# get: OrderedDict
>>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
#常规命令 delete
#返回值 成功删除 1 删除失败0
cache.delete('my_key')
#常规命令 delete_many
#返回值 成功删除的数据条数
cache.delete_many(['a', 'b', 'c'])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGZoNYM4-1579523427179)(images\浏览器缓存.png)]
浏览器缓存分类:
不会向服务器发送请求,直接从缓存中读取资源
1,Expires
缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点
Expires=max-age + 请求时间
Expires 是 HTTP/1 的产物,受限于本地时间,如 果修改了本地时间,可能会造成缓存失效
2, Cache-Control
在HTTP/1.1中,Cache-Control主要用于控制网页缓存。比如当Cache-Control:max-age=120
代表请求创建时间后的120秒,缓存失效
横向对比 Expires VS Cache-Control
**协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
1,Last-Modified和If-Modified-Since
第一次访问时,服务器会返回
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
浏览器下次请求时 携带If-Modified-Since这个header , 该值为 Last-Modified
服务器接收请求后,对比结果,若资源未发生改变,则返回304, 否则返回200并将新资源返回给浏览器
缺点:只能精确到秒,容易发生单秒内多次修改,检测不到
2,ETag和If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成
流程同上
对比 Last-Modified VS ETag
1,精度不一样 - Etag 高
2,性能上 - Last-Modifi 高
3,优先级 - Etag 高
django.utils.deprecation.MiddlewareMixin
类def process_request(self, request):
执行路由之前被调用,在每个请求上调用,返回None或HttpResponse对象def process_view(self, request, callback, callback_args, callback_kwargs):
调用视图之前被调用,在每个请求上调用,返回None或HttpResponse对象def process_response(self, request, response):
所有响应返回浏览器 被调用,在每个请求上调用,返回HttpResponse对象def process_exception(self, request, exception):
当处理过程中抛出异常时调用,返回一个HttpResponse对象def process_template_response(self, request, response):
在视图刚好执行完毕之后被调用,在每个请求上调用,返回实现了render方法的响应对象# file : middleware/mymiddleware.py
from django.http import HttpResponse, Http404
from django.utils.deprecation import MiddlewareMixin
class MyMiddleWare(MiddlewareMixin):
def process_request(self, request):
print("中间件方法 process_request 被调用")
def process_view(self, request, callback, callback_args, callback_kwargs):
print("中间件方法 process_view 被调用")
def process_response(self, request, response):
print("中间件方法 process_response 被调用")
return response
def process_exception(self, request, exception):
print("中间件方法 process_exception 被调用")
def process_template_response(self, request, response):
print("中间件方法 process_template_response 被调用")
return response
# file : settings.py
MIDDLEWARE = [
...
]
中间件的执行过程
练习
用中间件实现强制某个IP地址只能向/test 发送 5 次GET请求
提示:
答案:
跨站请求伪造攻击
说明:
CSRF中间件和模板标签提供对跨站请求伪造简单易用的防护。
作用:
解决方案:
取消 csrf 验证(不推荐)
django.middleware.csrf.CsrfViewMiddleware
的中间件通过验证 csrf_token 验证
需要在表单中增加一个标签
{
% csrf_token %}