1-Django4.2 - 缓存

before

Django4.2.3 + win11 + python3.10

Django缓存框架的管档,写的很好,非常值得一读:https://docs.djangoproject.com/zh-hans/4.2/topics/cache/

Django缓存框架的核心目标:https://docs.djangoproject.com/zh-hans/4.2/misc/design-philosophies/#cache-framework

缓存的好处无需多言,所以Django提供了专门的缓存框架来支持各种缓存:

  • 不同的缓存粒度,推荐程度由高到低排序:
    • 指定视图缓存,粒度适中。
    • 模板片段缓存,对模板文件的局部内容进行缓存,粒度较细。
    • 全站缓存,粒度最大。
    • 更低级别的缓存API,用来缓存Python中的对象(list、dict、模型对象...)。
  • 不同的缓存方式,推荐程度由高到低排序:
    • 第三方缓存数据库(redis、Memcache),专业的才是最好的嘛。另外,随着内存数据库的发展演变,Memcache不如redis用的多了。
    • 本地文件缓存,将渲染好的字符串缓存到文件中,下次查询省了渲染的步骤了,内存不大的小站点非常有用。
    • 本地数据库缓存,套路同本地文件缓存。
    • 本地内存缓存,内存大了啥都好说。
    • 虚拟缓存,用于开发,Django 带有一个实际上并不缓存的“虚拟”缓存——它只是实现了缓存接口而不做任何事情。

由于官档写的很详细了,本篇只做常用的配置和应用示例演示。

设置缓存

缓存系统需要少量的设置。也就是说,你必须告诉它你的缓存数据应该放在哪里 —— 是在数据库中,还是在文件系统上,或者直接放在内存中。这是一个重要的决定,会影响你的缓存的性能;是的,有些缓存类型比其他类型快。

缓存设置项位于你的配置文件的缓存配置中。这里有缓存配置所有可用值的说明。

缓存参数

这里来列一下公共的缓存参数:

  • TIMEOUT:用于缓存的默认超时,以秒为单位。此参数默认为300秒(5 分钟)。您可以设置TIMEOUTNone,默认情况下,缓存键永不过期。值0会导致键立即过期(实际上是“不缓存”)。
  • OPTIONS:应该传递给缓存后端的任何选项。每个后端的有效选项列表会有所不同,第三方库支持的缓存后端会将其选项直接传递给底层缓存库。
    • MAX_ENTRIES:删除旧值之前缓存中允许的最大条目数。此参数默认为300
    • CULL_FREQUENCY:当缓存条目达到MAX_ENTRIES时,剔除缓存中的比例,这个值必须是整数,默认是3,即剔除三分之一,如果是即剔除一半。存疑的是剔除的策略,我只查到了基于本地内存的缓存剔除策略是LRU,其它的貌似都是随机剔除。
  • KEY_PREFIX: 一个字符串,将自动包含(默认添加)到 Django 服务器使用的所有缓存键中。
  • VERSION:Django 服务器生成的缓存键的默认版本号。
  • KEY_FUNCTION 一个字符串,其中包含一个函数的虚线路径,该函数定义了如何将前缀、版本和密钥组合成最终的缓存密钥。

redis

现在redis数据库用的较多,所以放到最上面!但是django的缓存框架中并没有实现.....但django-redis模块实现了,所以:

先下载django-redis模块:

pip install django-redis

然后在settings.py中进行配置:

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        # "LOCATION": "redis://IP:PORT/可选的数据库参数",
        # "LOCATION": "redis://127.0.0.1:6379/0",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {
                "max_connections": 100
            },
            "DECODE_RESPONSES": True,  # True返回的数据自动decode
            "PASSWORD": "",  # 访问redis是否需要密码
        }
    }
}

具体的使用,参考:https://www.cnblogs.com/Neeo/articles/14269422.html

Memcache

现在由于Memcache用的不多了,这里仅作配置展示。

基于python-memcached模块连接memcache

settings.py中配置:

# 通过ip和port链接
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}
# 通过sock文件链接
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',
        ]
    }
}

基于pylibmc模块连接memcache

settings.py中配置:

# 通过ip和port链接
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': '127.0.0.1:11211',
    }
}
# 通过sock文件链接
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',
        ]
    }
}

本地内存缓存

如果你的配置文件中没有指定其他缓存,那么这是默认的缓存。如果你想获得内存缓存的速度优势,但又不具备运行 Memcached 的能力,可以考虑使用本地内存缓存后端。这个缓存是每进程所有和线程安全的。

在配置文件中进行配置即可:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',  # 唯一标识的key
    }
}

其他参数参考缓存参数章节。

本地文件缓存

基于文件的后端序列化并保存每个缓存值作为单独的文件。

在配置文件中进行配置即可:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',
        # 如果您使用的是 Windows,请将驱动器号放在路径的开头
        # 'LOCATION': 'c:/foo/bar',
    }
}

其他参数参考缓存参数章节。

目录路径应该是绝对路径——也就是说,它应该从文件系统的根目录开始。是否在设置的末尾加上斜线并不重要。

确保此设置指向的目录存在并且可读可写,或者它可以由运行 Web 服务器的系统用户创建。

本地数据库缓存

Django 可以在数据库中存储缓存数据。如果你有一个快速、索引正常的数据库服务器,这种缓存效果最好。

在配置文件中进行配置即可:

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

与其他缓存后端不同,数据库缓存不支持在数据库级别自动剔除过期条目。相反,每次调用add()set()或时都会剔除过期的缓存条目。

完事之后,就要创建缓存表了:

python manage.py createcachetable

这将在您的数据库中创建一个表格,该表格具有 Django 的数据库缓存系统所期望的正确格式。表名取自 LOCATION

如果是多数据库的话,需要单独配置,参考管档吧:https://docs.djangoproject.com/zh-hans/4.2/topics/cache/#multiple-databases

虚拟缓存(用于开发模式)

最后,Django 带有一个实际上不是缓存的 “虚拟” 缓存,它只是实现缓存接口,并不做其他操作。

如果你有一个生产网站,在不同的地方使用了大量的缓存,但在开发/测试环境中,你不想缓存,也不想单独修改你的代码,那么这就很有用。

你只需要在配置文件中进行配置即可:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
    }
}

应用缓存

这里以本地内存缓存作为缓存配置,你可以在settings.py文件中添加如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 最大缓存个数(默认300)
            'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        },
    }
}

一旦缓存设置完毕,就可以在项目中进行应用了。

局部视图缓存

settings.py中配置不变。

应用时有两种,分别是视图中以装饰器的形式和在路由上进行添加。

视图中应用缓存

views.py

import time
from django.shortcuts import render, HttpResponse, redirect
# 必须导入缓存装饰器
from django.views.decorators.cache import cache_page


@cache_page(5)  # 缓存单位:秒
def index(request):
    ctime = time.time()
    return HttpResponse(ctime)

urls.py

from django.contrib import admin
from django.urls import path
from api import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
]

浏览器访问的话,每五秒才会刷新一次,因为缓存时间是5秒。

在路由中应用缓存

urls.py

from django.contrib import admin
from django.urls import path
from django.views.decorators.cache import cache_page
from api import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', cache_page(5)(views.index)),
]

views.py

import time
from django.shortcuts import render, HttpResponse, redirect
# 必须导入缓存装饰器
# from django.views.decorators.cache import cache_page


# @cache_page(5)  # 缓存单位是秒
def index(request):
    ctime = time.time()
    return HttpResponse(ctime)

浏览器访问效果跟上面的一样。

模板片段缓存

可以在模板中对局部进行更细粒度的缓存。

index.html

{% load cache %} <!-- 必须声明 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h3>未缓存的</h3>
<p>{{ ctime }}</p>
<p>{{ now }}</p>
<h3>使用缓存</h3>
<!-- 缓存内容 -->
{% cache 5 'unique-snowflake' %}
    <p>{{ ctime }}</p>
    <p>{{ now }}</p>
{% endcache %}
</body>
</html>

urls.py

from django.contrib import admin
from django.urls import path
# from django.views.decorators.cache import cache_page
from api import views

urlpatterns = [
    path('admin/', admin.site.urls),
    # path('index/', cache_page(5)(views.index)),
    path('index/', views.index),
]

views.py

import time
import datetime
from django.shortcuts import render, HttpResponse, redirect

def index(request):
    ctime = time.time()
    now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    return render(request, 'index.html', {"ctime": ctime, 'now': now})

更多参考管档吧:https://docs.djangoproject.com/zh-hans/4.2/topics/cache/#template-fragment-caching

全栈缓存

全站缓存的配置需要用到中间件和其他参数,settings.py

MIDDLEWARE = [
    # 下面这个缓存中间件必须放在所有中间件的最上面
    "django.middleware.cache.UpdateCacheMiddleware",
	....
    # 下面这个缓存中间件必须放在所有中间件的最下面
    "django.middleware.cache.FetchFromCacheMiddleware",
]

# 我这里将cache缓存由本地内存缓存更换为了Redis
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://:@127.0.0.1:6379/0",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "PASSWORD": "1234",  # 密码,如果没有设置密码,这个参数可以注视掉
            'MAX_ENTRIES': 300,  # 最大缓存个数(默认300)
            'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        }
    }
}
# 默认超时时间是300秒,我们可以通过CACHE_MIDDLEWARE_SECONDS来修改
CACHE_MIDDLEWARE_SECONDS = 10
# 下面是关于key的,咱们这里保持默认就完了
CACHE_MIDDLEWARE_KEY_PREFIX = ""
# 用于存储的缓存别名,没想好的,指定个default就行
CACHE_MIDDLEWARE_ALIAS = "default"

urls.py

from django.contrib import admin
from django.urls import path
# from django.views.decorators.cache import cache_page
from api import views

urlpatterns = [
    path('admin/', admin.site.urls),
    # path('index/', cache_page(5)(views.index)),
    path('index/', views.index),
]

views.py

import time
import datetime
from django.shortcuts import render, HttpResponse, redirect

def index(request):
    ctime = time.time()
    now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    return render(request, 'index.html', {"ctime": ctime, 'now': now})

index.html

{% load cache %} <!-- 必须声明 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h3>未缓存的</h3>
<p>{{ ctime }}</p>
<p>{{ now }}</p>
<h3>使用缓存</h3>
<!-- 缓存内容 -->
{% cache 5 'unique-snowflake' %}
    <p>{{ ctime }}</p>
    <p>{{ now }}</p>
{% endcache %}
</body>
</html>

注意,如果同时使用了全栈缓存和局部模板片段缓存,那么全栈缓存的优先级高。

see also: https://www.cnblogs.com/wupeiqi/articles/5246483.html

posted @ 2023-07-29 14:56  听雨危楼  阅读(167)  评论(0编辑  收藏  举报