浅谈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
用Python删除本地目录下某一时间点之前创建的所有文件的实例
Dec 14 Python
浅谈Tensorflow由于版本问题出现的几种错误及解决方法
Jun 13 Python
Windows系统下PhantomJS的安装和基本用法
Oct 21 Python
对pandas将dataframe中某列按照条件赋值的实例讲解
Nov 29 Python
python实现windows壁纸定期更换功能
Jan 21 Python
python中数组和矩阵乘法及使用总结(推荐)
May 18 Python
pytorch 自定义参数不更新方式
Jan 06 Python
python对指定字符串逆序的6种方法(小结)
Apr 02 Python
python多进程使用函数封装实例
May 02 Python
python 用opencv实现霍夫线变换
Nov 27 Python
Python 用__new__方法实现单例的操作
Dec 11 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者的疑难问答(2)
2006/10/09 PHP
PHP中的类-什么叫类
2006/11/20 PHP
PHP的开发框架的现状和展望
2007/03/16 PHP
Mysql数据库操作类( 1127版,提供源码下载 )
2010/12/02 PHP
又一个PHP实现的冒泡排序算法分享
2014/08/21 PHP
Laravel最佳分割路由文件(routes.php)的方式
2016/08/04 PHP
zend框架实现支持sql server的操作方法
2016/12/08 PHP
php实现解析xml并生成sql语句的方法
2018/02/03 PHP
php微信扫码支付 php公众号支付
2019/03/24 PHP
jQuery 1.8 Release版本发布了
2012/08/14 Javascript
浅析jquery某一元素重复绑定的问题
2014/01/03 Javascript
JavaScript排序算法之希尔排序的2个实例
2014/04/04 Javascript
JavaScript中使用stopPropagation函数停止事件传播例子
2014/08/27 Javascript
javascript实现根据iphone屏幕方向调用不同样式表的方法
2015/07/13 Javascript
js验证身份证号有效性并提示对应信息
2015/10/19 Javascript
jQuery获取父元素节点、子元素节点及兄弟元素节点的方法
2016/04/14 Javascript
Vue-resource实现ajax请求和跨域请求示例
2017/02/23 Javascript
Vue实现自带的过滤器实例
2017/03/09 Javascript
JavaScript实现form表单的多文件上传
2020/03/27 Javascript
利用jqprint插件打印页面内容的实现方法
2018/01/09 Javascript
基于webpack-hot-middleware热加载相关错误的解决方法
2018/02/22 Javascript
Angular搜索场景中使用rxjs的操作符处理思路
2018/05/30 Javascript
JavaScript中import用法总结
2019/01/20 Javascript
浅析vue-router中params和query的区别
2019/12/24 Javascript
基于jquery实现彩色投票进度条代码解析
2020/08/26 jQuery
Python中常用的os操作汇总
2020/11/05 Python
python 实用工具状态机transitions
2020/11/21 Python
惠普墨西哥官方商店:HP墨西哥
2016/12/01 全球购物
网友共享的几个面试题关于Java和Unix等方面的
2016/09/08 面试题
2014年驾驶员工作总结
2014/11/18 职场文书
小学生作文批改评语
2014/12/25 职场文书
工程部岗位职责
2015/02/10 职场文书
超市收银员岗位职责
2015/04/07 职场文书
兴趣班停课通知
2015/04/24 职场文书
大学生学习十八届五中全会精神心得体会
2016/01/05 职场文书
SpringBoot整合minio快速入门教程(代码示例)
2022/04/03 Java/Android