浅谈Django的缓存机制


Posted in Python onAugust 23, 2018

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

  1. 开发调试
  2. 内存
  3. 文件
  4. 数据库
  5. Memcache缓存(python-memcached模块)
  6. Memcache缓存(pylibmc模块)

通用配置

'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

开发调试

# 此为开始调试用,实际内部不做任何操作
  # 配置:
    CACHES = {
      'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',   # 引擎
       通用配置
      }
    }

内存

# 此缓存将内容保存至内存的变量中
  # 配置:
    CACHES = {
      'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
       通用配置
      }
    }

  # 注:其他配置同开发调试版本

文件

# 此缓存将内容保存至文件
  # 配置:

    CACHES = {
      'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',
         通用配置
      }
    }
  # 注:其他配置同开发调试版本

数据库

# 此缓存将内容保存至数据库

  # 配置:
    CACHES = {
      'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table', # 数据库表
       通用配置
      }
    }

  # 注:执行创建表命令 python manage.py createcachetable

Memcache缓存(python-memcached模块)

# 此缓存使用python-memcached模块连接memcache

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

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

  CACHES = {
    'default': {
      'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
      'LOCATION': [
        '172.19.26.240:11211',
        '172.19.26.242:11211',
      ]
    }
  }

Memcache缓存(pylibmc模块)

# 此缓存使用pylibmc模块连接memcache
  
  CACHES = {
    'default': {
      'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
      'LOCATION': '127.0.0.1:11211',
    }
  }

  CACHES = {
    'default': {
      'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
      'LOCATION': '/tmp/memcached.sock',
    }
  } 

  CACHES = {
    'default': {
      'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
      'LOCATION': [
        '172.19.26.240:11211',
        '172.19.26.242:11211',
      ]
    }
  }

缓存的应用

单独视图缓存

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request):
      ...

即通过装饰器的方式实现,导入模块之后,在需要缓存的函数前加@cache_page(60 * 15) 60*15表示缓存时间是15分钟

例子如下:

from django.views.decorators.cache import cache_page
@cache_page(10)
def cache(request):
  import time
  ctime = time.time()
  return render(request,"cache.html",{"ctime":ctime})

前端页面如下:

<!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>

这样在前端页面在获取的ctime的时候就会被缓存10秒钟,10秒钟之后才会变化,但是这样的话就相当月所有的调用ctime的地方都被缓存了

局部缓存

引入TemplateTag

{% load cache %}

使用缓存

{% cache 5000 缓存key %}

缓存内容

{% endcache %}

更改前端代码如下:

{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <h1>{{ ctime }}</h1>
  <h1>{{ ctime }}</h1>
  {% cache 10 c1 %}
  <h1>{{ ctime }}</h1>
  {% endcache %}
</body>
</html>

这样就实现了最后一个ctime缓存,其他两个不缓存

全站缓存

全站缓存的时候,需要在中间件的最上面添加:

'django.middleware.cache.UpdateCacheMiddleware',

在中间件的最下面添加:

'django.middleware.cache.FetchFromCacheMiddleware',

其中'django.middleware.cache.UpdateCacheMiddleware'里面只有process_response方法,在'django.middleware.cache.FetchFromCacheMiddleware'中只有process_request方法,所以最开始是直接跳过UpdateCacheMiddleware,然后从第一个到最后一个中间件的resquest,第一次没有缓存座椅匹配urls路由关系依次进过中间件的process_view,到达views函数,再经过process_exception最后经过response,到达FetchFromCacheMiddleware

另一个让我烦恼一个多小时的问题是,设置 TIMEOUT 参数无效。查找Django的源文件( ./core/cache/backends/memcached.py ),打印出设置缓存时的信息。发现不论参数设置多少,缓存的有效期都变成了600s。

后来终于在django的 conf/global_settings.py 这个文件里找到 CACHE_MIDDLEWARE_SECONDS = 600 这个参数。看名字是中间件的缓存时间,懒得深究了。在 settings.py 文件中把这个参数值也修改一下,再次测试,终于得到预期的效果。这个问题竟然在放狗都没搜到,值得一记。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python 实现文件的递归拷贝实现代码
Aug 02 Python
解决python3 urllib中urlopen报错的问题
Mar 25 Python
python读取二进制mnist实例详解
May 31 Python
python3获取两个日期之间所有日期,以及比较大小的实例
Apr 08 Python
基于python 处理中文路径的终极解决方法
Apr 12 Python
python之cv2与图像的载入、显示和保存实例
Dec 05 Python
Python实现图片转字符画的代码实例
Feb 22 Python
python日志logging模块使用方法分析
May 23 Python
Python 使用 Pillow 模块给图片添加文字水印的方法
Aug 30 Python
如何用OpenCV -python3实现视频物体追踪
Dec 04 Python
Python多线程Threading、子线程与守护线程实例详解
Mar 24 Python
基于python生成英文版词云图代码实例
May 16 Python
如何在python字符串中输入纯粹的{}
Aug 22 #Python
关于python列表增加元素的三种操作方法
Aug 22 #Python
Python Learning 列表的更多操作及示例代码
Aug 22 #Python
Python绘制的二项分布概率图示例
Aug 22 #Python
使用Python写一个量化股票提醒系统
Aug 22 #Python
Python使用numpy产生正态分布随机数的向量或矩阵操作示例
Aug 22 #Python
用Python将mysql数据导出成json的方法
Aug 21 #Python
You might like
随机头像PHP版
2006/10/09 PHP
Zend 输出产生XML解析错误
2009/03/03 PHP
php全角字符转换为半角函数
2014/02/07 PHP
php的dl函数用法实例
2014/11/06 PHP
怎么让脚本或里面的函数在所有图片都载入完毕的时候执行
2006/10/17 Javascript
把textarea中字符串里含有的回车换行替换成&amp;lt;br&amp;gt;的javascript代码
2007/04/20 Javascript
jquery 必填项判断表单是否为空的方法
2008/09/14 Javascript
Javascript 判断客户端浏览器类型代码
2010/03/01 Javascript
jQuery获得字体颜色16位码的方法
2016/02/20 Javascript
JavaScript知识点总结(十)之this关键字
2016/05/31 Javascript
基于jQuery实现Accordion手风琴自定义插件
2020/10/13 Javascript
微信小程序获取手机网络状态的方法【附源码下载】
2017/12/08 Javascript
jquery 实现拖动文件上传加载进度条功能
2018/03/18 jQuery
vue小白入门教程
2018/04/02 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
微信小程序中为什么使用var that=this
2019/08/27 Javascript
layui导出所有数据的例子
2019/09/10 Javascript
layui实现把数据表格时间戳转换为时间格式的例子
2019/09/12 Javascript
使用Layer组件弹出多个对话框(非嵌套)与关闭及刷新的例子
2019/09/25 Javascript
[02:08]我的刀塔不可能这么可爱 胡晓桃_1
2014/06/20 DOTA
[41:56]Spirit vs Liquid Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
pyv8学习python和javascript变量进行交互
2013/12/04 Python
Python使用bs4获取58同城城市分类的方法
2015/07/08 Python
详解Django中的过滤器
2015/07/16 Python
在Ubuntu系统下安装使用Python的GUI工具wxPython
2016/02/18 Python
python中 chr unichr ord函数的实例详解
2017/08/06 Python
Python多进程并发与多线程并发编程实例总结
2018/02/08 Python
pytorch 利用lstm做mnist手写数字识别分类的实例
2020/01/10 Python
Python Opencv实现单目标检测的示例代码
2020/09/08 Python
简单整理HTML5的基本特性和语法
2016/02/18 HTML / CSS
2014年服务员工作总结
2014/11/18 职场文书
2014年财务工作总结与计划
2014/12/08 职场文书
工程部岗位职责
2015/02/10 职场文书
民政工作个人总结
2015/02/28 职场文书
求职信范文怎么写
2015/03/19 职场文书
厉害!这是Redis可视化工具最全的横向评测
2021/07/15 Redis