Django 之 缓存框架

Django提供了一套强大的缓存框架,包括多种缓存后端如内存、文件、数据库和Memcached,用于提升网站性能,减少数据库访问。缓存可应用于全站、视图和模板片段,通过中间件和装饰器实现。Memcached作为一种高效的内存缓存服务,常被大型网站使用,但需要注意断电数据丢失的问题。配置缓存时,可设置TIMEOUT、OPTIONS等参数以控制缓存行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Django的缓存

​ 动态网站的不足之处体现在“动态”上。每请求一个页面,Web 服务器都要做各种计算,为了让用户可以看到页面,要查询数据库、渲染模板,还要执行一些业务逻辑。从消耗方面来看,这个过程比从文件系统中读取一个文件要耗资源。

Django 提供了一个强健的缓存系统,能把动态页面保存起来,不用每次请求都重新生成。为了便于使用,Django 提供的缓存分为不同的粒度层次,可以缓存特定视图的输出、可以只缓存不易生成的片段,也可以缓存整个网站。

配置缓存

开发调试

Django提供了一个虚拟的缓存,它并不是真正的缓存,只是实现了缓存接口。

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': 'c:/foo/bar',
    }
}

数据库缓存

Django 可以把缓存数据存入数据库。如果数据库服务器的索引稳定快速,这样做效果最好。以数据表为缓存后端的步骤如下:

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

但是在某些情况下,还是有一些用途的,比如你有一个高速、高效索引的数据库。

注意,创建缓存的数据库表使用的语句:

python manage.py createcachetable

Memcached

Memcached是Django原生支持的缓存系统,速度快,效率高。Memcached是一种基于内存的缓存服务,起初是为了解决LiveJournal.com的负载问题而开发的,后来由Danga开源。 它被类似Facebook和维基百科这种大型网站使用,用来减少数据库访问次数,显著地提高了网站的性能。

Memcached会启动一个守护进程,并分配单独的内存块。其主要工作就是为缓存提供一个快速的添加,检索,删除的接口。所有的数据直接存储在内存中,所以它不能取代数据库或者文件系统的功能。如果你对缓存很熟悉,这些内容都很好理解。

需要注意的是:

  • Memcached不是Django自带的软件,而是一个独立的软件,需要你自己安装、配置和启动服务;
  • Memcached安装好了后,还要安装Python操作Memcached的依赖库,最常用的是python-memcached和pylibmc;
  • 上面两个条件都满足了后,还要在Django中进行配置。

配置方法:

  • 根据你安装的Python依赖库不同,将CACHES的BACKEND设置为

    django.core.cache.backends.memcached.MemcachedCache
    或者
    django.core.cache.backends.memcached.PyLibMCCache
    
  • 设置LOCATION为你的Memecached守护进程所在的主机IP和进程端口,格式为ip:port的字符串。或者unix:path的形式,在Unix操作系统中。

下面是一个参考例子,Memcached运行在localhost (127.0.0.1) port 11211,使用了python-memcached库:

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

下面的Memcached运行在本地的Unix socket上:/tmp/memcached.sock,依赖python-memcached

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

下面的Memcached运行在/tmp/memcached.sock,不带unix:/前缀,依赖pylibmc库:

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

Memcached支持分布式服务,可能同时在几台机器上运行,将它们的IP地址都加入到LOCATION中,如下所示:

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

基于内存的缓存系统有个明显的缺点就是断电数据丢失,尤其是Memcached这种不支持序列化的缓存,所以请大家务必要注意数据的安全性。

缓存参数

上述每一个缓存后端都可以设置一些额外的参数来控制缓存行为,可以设置的参数如下:

  • TIMEOUT:缓存的默认过期时间,以秒为单位,默认是300秒None表示永远不会过期。设置成0将造成缓存立即失效(缓存就没有意义了)。

  • OPTIONS:可选参数,根据缓存后端的不同而不同。

  • KEY_PREFIX:Django服务器使用的所有缓存键的字符串。

  • VERSION:由Django服务器生成的默认版本号。

  • KEY_FUNCTION:一个字符串,其中包含一个函数的点路径,该函数定义了如何将前缀,版本和密钥组合成最终缓存密钥。

文件缓存是参数配置实例:

CACHES = {
 'default': {
  'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', #指定缓存使用的引擎
  'LOCATION': '/var/tmp/django_cache',        #指定缓存的路径
  'TIMEOUT':300,              #缓存超时时间(默认为300秒,None表示永不过期)
  'OPTIONS':{
   'MAX_ENTRIES': 300,            # 最大缓存记录的数量(默认300)
   'CULL_FREQUENCY': 3,           # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  }
 }   
}

Django中的缓存应用

缓存全站

缓存系统最简单的使用方法是缓存整个网站。

这需要额外将’django.middleware.cache.UpdateCacheMiddleware’和’django.middleware.cache.FetchFromCacheMiddleware’添加到MIDDLEWARE设置中,如下所示:

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
]

注意update中间件必须放在列表的开始位置,而fectch中间件,必须放在最后。 这是Django使用中间件的规则,它们是有顺序关系的。

然后,添加下面这些需要的参数到settings文件里:

CACHE_MIDDLEWARE_ALIAS : 用于存储的缓存的别名
CACHE_MIDDLEWARE_SECONDS : 每个page需要被缓存多少秒.
CACHE_MIDDLEWARE_KEY_PREFIX : 密钥前缀

缓存视图

另一个使用缓存框架的方法是对视图的输出进行缓存。在django.views.decorators.cache定义了一个自动缓存视图响应结果的装饰器cache_page,使用非常简单:

from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def my_view(request):
    ...

cache_page接受一个参数:timeout,秒为单位。在上例中,my_view()视图的结果将被缓存15分钟(为了提高可读性写成了60 * 15)

和整站缓存一样,一个URL对应一个键。如果多个URL指向同一视图,每个URL将会分别缓存。 继续my_view的例子,如果URLconf如下所示:

urlpatterns = [
    url(r'^foo/([0-9]{1,2})/$', my_view),
]

那么发送到/foo/23//foo/1/的请求会被分别缓存。但是一旦一个明确的URL(例如/foo/23/) 已经被请求过了, 之后再度发出的指向该URL的请求将使用缓存的内容。

cache_page也可以使用一些额外的参数,比如cache,这个参数指示具体使用的缓存后端。

@cache_page(60 * 15, cache="special_cache")
def my_view(request):
    ...

还可以采用可选的关键字参数key_prefix在每个视图中指定具体的缓存前缀,如下所示:

@cache_page(60 * 15, key_prefix="site1")
def my_view(request):
    ...

缓存模板片段

我们还可以使用cache模板标签来缓存模板的一个片段。要使用这个标签,首先要在模版的顶部位置添加{% load cache %}

模板标签{% cache %}将在设定的时间内,缓存标签块中包含的内容。它最少需要两个参数:缓存时间(以秒为单位)以及给缓存片段起的名称。像这样:

{% load cache %}
{% cache 500 sidebar %}
    .. sidebar ..
{% endcache %}

还可以依据片段内的动态内容缓存多个版本。如上个例子中,可以给站点的每个用户生成不同版本的sidebar缓存。 只需要给{% cache %}标签再传递一个参数来标识区分这个缓存片段,如下所示:

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

缓存超时参数可以是个模板变量,只要模板变量可以解析为整数值即可。例如,如果模板变量my_timeout设置为值600,则以下两个示例是等效的:

{% cache 600 sidebar %} ... {% endcache %}
{% cache my_timeout sidebar %} ... {% endcache %}

实例:

views视图函数

from django.views.decorators.cache import cache_page
import time
from .models import *
def index(request):
     t=time.time()      #获取当前时间
     bookList=Book.objects.all()
     return render(request,"index.html",locals())

模板(index.html):

{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 <h3 style="color: green">不缓存:-----{{ t }}</h3>
{% cache 2 'name' %}
 <h3>缓存:-----:{{ t }}</h3>
{% endcache %}
</body>
</html> 

前后端分离

设置值跟取值:

from django.core.cache import cache
# 设置缓存
cache.set('test_data',{'name':'linwow'},5)
# 获取缓存
cache.get('test_data')

高级用法

rom django.core.cache import cache
# 设置:cache.set(键,值,有效时间)
cache.set('my_key', 'hello, world!', 30)
cache.add('add_key', 'New value')
cache.set_many({'a': 1, 'b': 2, 'c': 3})

# 获取:cache.get(键)
cache.has_key('v') #判断key为v是否存在
cache.get('my_key')
cache.get('my_key', 'has expired')
cache.get_many(['a', 'b', 'c'])

# 删除:cache.delete(键)
cache.delete('key')
cache.delete_many(['a', 'b', 'c'])

# 清空:cache.clear() 
cache.clear()

# 增加时间
cache.set('num', 1)
cache.incr('num') # 每次默认增加1秒
cache.incr('num', 10) # 在原来的时间上增加10秒

# 减少时间
cache.decr('num') # 每次默认减少一秒
cache.decr('num', 5) # 在原来的时间上减去5秒

# 禁用客户端缓
# 如果你不在视图中使用缓存,服务器端是肯定不会缓存的,然而用户的客户端如浏览器还是会缓存一些数据,这时你可以使用never_cache禁用掉客户端的缓存。
from django.views.decorators.cache import never_cache
@never_cache
def index(request):
    pass
# views.py
from django.views.decorators.cache import never_cache
class MyTime(View):
    @never_cache
    def get(self, request):
        timer = time.time()
        return HttpResponse(timer)
@never_cache
def myFun(request):
    timer = time.time()
    return HttpResponse(timer)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值