当前位置: 首页 > news >正文

10、Django开发总结:Django缓存Cache应用场景、设置以及高级使用技巧

缓存(Cache)对于创建一个高性能的网站和提升用户体验来说是非常重要的,本篇介绍缓存Cache应用场景及工作原理,并详细介绍如何在Django中设置Cache并使用它们。下一篇介绍缓存的使用原理,比如Django是如何将数据存储到选定介质的以及django是如何判断缓存是否已经过期的。

缓存Cache

缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用的介质是读取速度很快的内存。一般来说从数据库多次把所需要的数据提取出来,要比从内存或者硬盘等一次读出来付出的成本大很多。对于中大型网站而言,使用缓存减少对数据库的访问次数是提升网站性能的关键之一。

为什么要使用缓存Cache

在Django中,当用户请求到达视图后,视图会先从数据库提取数据放到模板中进行动态渲染,渲染后的结果就是用户看到的网页。如果用户每次请求都从数据库提取数据并渲染,将极大降低性能,不仅服务器压力大,而且客户端也无法即时获得响应,这样容易导致服务器过载,并浪费服务器资源。如果能将渲染后的结果放到速度更快的缓存中,每次有请求过来,先检查缓存中是否有对应的资源,如果有,直接从缓存中取出来返回响应,节省取数据和渲染的时间,不仅能大大提高系统性能,还能提高用户体验(适用于静态页面或变化不频繁的页面)。

Django提供了不同级别的缓存粒度,可以缓存特定视图的输出,或只缓存某些特定的片段,也可以缓存整个站点。

每次当访问首页时,下面视图都会从数据库中提取文章列表,并渲染到模板里去。大多数情况下的博客不会更新得那么频繁,所以文章列表是不变的。这样用户在一定时间内多次访问首页时都从数据库重新读取同样的数据是一种很大的浪费。

from django.shortcuts import render

def index(request):
    # 读取数据库等并渲染到网页
   article_list = Article.objects.all()
   return render(request, 'index.html', {'article_list': article_list})

使用缓存Cache就可以帮解决这个问题。当用户首次访问博客首页时,从数据库中提取文章列表,并将其存储到缓存里(常用的是内存,这取决于项目设置)。当用户在单位时间内再次访问首页时, Django先检查缓存是否过期(本例是1个小时), 再检查缓存里文章列表资源是否存在,如果存在,直接从缓存中读取数据, 并渲染模板。

from django.shortcuts import render
from django.views.decorators.cache import cache_page

@cache_page(60 * 60) # 缓存失效秒数,此处缓存1个小时
def index(request):
    article_list = Article.object.all()
    return render(request, 'index.html', {"article_list": article_list})

注意: 在Django中使用缓存前,必需先做必要的设置。本篇是关于memcached的使用配置。Redis是基于内存的缓存型数据库,同时支持数据序列化相比而言更加安全,生产环境大多使用的一种缓存,Redis的详细缓存参数设置见:

25、Django开发总结:settings.py设置选项详解_django settings.py_SteveRocket的博客-CSDN博客

缓存Cache的应用场景

缓存主要适用于对页面实时性要求不高的页面。存放在缓存的数据,通常是频繁访问的,而不会经常修改的数据,如:

  1. 博客文章。假设用户一天更新一篇文章,那么可以为博客设置1天的缓存,一天后会刷新。
  2. 购物网站。商品的描述信息几乎不会变化,而商品的购买数量需要根据用户情况实时更新。可以只选择缓存商品描述信息。
  3. 缓存网页片段。比如缓存网页导航菜单和脚部(Footer)。

Django缓存设置

Django中提供了多种缓存方式,如果要使用缓存,需要先在settings.py中进行配置,然后应用。根据缓存介质的不同,需要设置不同的缓存后台Backend。

Django提供多种缓存机制,如下所示:

  1. 开发调试缓存
  2. 本地内存缓存
  3. 数据库缓存
  4. 文件缓存
  5. Memcache
  6. Redis

Memcached缓存

Memcached是基于内存的缓存,Django原生支持的最快最有效的缓存系统。对于大多数场景,推荐使用Memcached,数据缓存在服务器端。使用前需要通过pip安装memcached的插件python-memcached和pylibmc,可以同时支持多个服务器上面的memcached。

下面是使用pyhon-memcached的设置。

# localhost
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
	'LOCATION': '127.0.0.1:11211',
    }
}

# unix soket
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': 'unix:/tmp/memcached.sock',
    }
}   

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
            '192.168.1.89:11211',
            '192.168.1.90:11211',
        ]
        # 也可以给缓存机器加权重,权重高的承担更多的请求,如下
        'LOCATION': [
            ('192.168.1.89:11211',5),
            ('192.168.1.90:11211',1),
        ]
    }
 }

 

数据库缓存

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table',
    }

文件系统缓存

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',#这个是文件夹的路径
      # 'LOCATION': 'c:\tmp\bar',#windows下的示例
    }
}

本地内存缓存

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake'
    }
}

Django中使用Cache

当做好Cache的设置后,在代码中可以有三种方式使用Cache。

  • 在视图View中使用
  • 在路由URLConf中使用
  • 在模板中使用
  1. 在函数视图View中使用cache
    from django.shortcuts import render
    from django.views.decorators.cache import cache_page
    
    # 在函数视图View中使用cache
    @cache_page(60 * 60) # 缓存失效秒数,此处缓存1个小时
    def index(request):
        article_list = Article.object.all()
        return render(request, 'index.html', {"article_list": article_list})

  2. 在路由URLConf中使用cache

这种不用修改负责逻辑部分的view。

from django.views.decorators.cache import cache_page

urlpatterns = [
    path('foo/<int:code>/', cache_page(60 * 15)(my_view)),
]

   3.在模板中使用cache

{% load cache %}
{% cache 500 sidebar request.user.username %}
    .. sidebar for logged in user ..
{% endcache %}

Cache的高级使用技巧

1、使用cache_control

通常用户将会面对两种缓存:浏览器缓存(私有缓存)以及提供者缓存(公共缓存)。 公共缓存由多个用户使用,而受其它人的控制。 这就产生了不想遇到的敏感数据的问题,比如说银行账号被存储在公众缓存中。 因此,Web 应用程序需要以某种方式告诉缓存那些数据是私有的,哪些是公共的。

解决方案是标示出某个页面缓存应当是私有的。 要在 Django 中完成此项工作,可使用 cache_control 视图修饰器:

from django.views.decorators.cache import cache_control

@cache_control(private=True)
def my_view(request):
# ...

该修饰器负责在后台发送相应的 HTTP 头部。

还有一些其他方法可以控制缓存参数。 例如, HTTP 允许应用程序执行如下操作:

  1. 定义页面可以被缓存的最大时间。
  2. 指定某个缓存是否总是检查较新版本,仅当无更新时才传递所缓存内容。

在 Django 中,可使用 cache_control 视图修饰器指定这些缓存参数。

from django.views.decorators.cache import cache_control

@cache_control(must_revalidate=True, max_age=3600)
def index10(request):
    """
    cache_control 告诉缓存对每次访问都重新验证缓存并在最长 3600 秒内保存所缓存版本。
    :param request:
    :return:
    """
    return HttpResponse("cache control must revalidate")

在 cache_control() 中,任何合法的Cache-Control HTTP 指令都是有效的。下面是完整列表:

  • public=True
  • private=True
  • no_cache=True
  • no_transform=True
  • must_revalidate=True
  • proxy_revalidate=True
  • max_age=num_seconds
  • s_maxage=num_seconds

2、使用vary_on_headers、vary_on_cookie

缺省情况下,Django 的缓存系统使用所请求的路径(如blog/article/1)来创建其缓存键。这意味着不同用户请求同样路径都会得到同样的缓存版本,不考虑客户端user-agent, cookie和语言配置的不同, 除非使用Vary头部通知缓存机制需要考虑请求头里的cookie和语言的不同。

要在 Django 完成这项工作,可使用便利的 vary_on_headers 视图装饰器。

from django.views.decorators.vary import vary_on_headers

@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
    ...

一个请求带有用户代理 Mozilla 和 cookie 值 foo=bar 被认为和用户代理 Mozilla 和 cookie 值 foo=ham 是不同的。因为 cookie 的变化如此普遍,所以这里有个 django.views.decorators.vary.vary_on_cookie() 装饰器。下面两个视图是等价的:

@vary_on_cookie
def my_view(request):
    ...

@vary_on_headers('Cookie')
def my_view(request):
	...

 

Vary请求头定义了高速缓存机制建立其缓存键时应该考虑到哪些请求头。

请求头参考:Django’s cache framework | Django documentation | Django

  1. 使用never_cache禁用缓存

如果想用头部完全禁掉缓存, 可以使用django.views.decorators.cache.never_cache装饰器。如果不在视图中使用缓存,服务器端是肯定不会缓存的,然而用户的客户端如浏览器还是会缓存一些数据,这时可以使用never_cache禁用掉客户端的缓存。

from django.views.decorators.cache import never_cache
@never_cache
def index13(request):
    """
    使用never_cache禁用掉客户端的缓存
    :param request:
    :return:
    """
    return HttpResponse("never cache")

参考文章:

Django’s cache framework | Django documentation | Django

25、Django开发总结:settings.py设置选项详解_django settings.py_SteveRocket的博客-CSDN博客

输入才有输出,吸收才能吐纳。——码字不易

相关文章:

  • 【黑客技术】LOIC —— 低轨道离子炮工具使用
  • 华为OD机试用java实现 -【吃火锅】
  • C语言 —— 数组
  • 35岁大龄程序员职业转型规划
  • IntelliJ IDEA 2023.1 最新变化
  • Qt音视频开发22-音频播放QAudioOutput
  • 递归--【天梯L2】愿天下有情人都是失散多年的兄妹
  • 第七章 react组件实例中三大属性之props
  • 面试官:Tomcat 在 SpringBoot 中是如何启动的(一)
  • 【人工智能与深度学习】判别性循环稀疏自编码器和群体稀疏性
  • 【计算机视觉 | 目标检测】BARON:pseudo words 和 linear layer 的理解
  • 【Git从入门到精通】分支机制
  • 【jvm系列-04】精通运行时数据区共享区域---堆
  • 【机器学习】P10 从头到尾实现一个线性回归案例
  • 四个常见的Linux面试问题
  • 【Leetcode】104. 二叉树的最大深度
  • Android单元测试 - 几个重要问题
  • Consul Config 使用Git做版本控制的实现
  • CSS3 变换
  • JavaScript学习总结——原型
  • JS数组方法汇总
  • Python3爬取英雄联盟英雄皮肤大图
  • ViewService——一种保证客户端与服务端同步的方法
  • yii2权限控制rbac之rule详细讲解
  • 阿里云前端周刊 - 第 26 期
  • 大整数乘法-表格法
  • 构建工具 - 收藏集 - 掘金
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 使用parted解决大于2T的磁盘分区
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • # Redis 入门到精通(一)数据类型(4)
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (论文阅读30/100)Convolutional Pose Machines
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (推荐)叮当——中文语音对话机器人
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • .Net Core和.Net Standard直观理解
  • .NET/C# 使窗口永不获得焦点
  • .NET处理HTTP请求
  • .net网站发布-允许更新此预编译站点
  • .net专家(高海东的专栏)
  • .Net组件程序设计之线程、并发管理(一)
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • .ui文件相关
  • .考试倒计时43天!来提分啦!
  • 。。。。。
  • ??javascript里的变量问题
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [100天算法】-x 的平方根(day 61)
  • [ASP.NET MVC]Ajax与CustomErrors的尴尬
  • [BZOJ2208][Jsoi2010]连通数
  • [C#7] 1.Tuples(元组)