赶塑坠 发表于 2025-9-30 11:26:49

Django缓存

Django提供了强大的缓存框架,可以帮助你提高网站性能。
1、缓存配置

Django 支持多种缓存后端,你可以根据项目规模、性能需求和基础设施来灵活选择。配置在 settings.py的 CACHES设置中完成
# settings.py

CACHES = {
    'default': {
      'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
      'LOCATION': 'unique-snowflake',
      'TIMEOUT': 300,# 默认缓存时间(秒),None 表示永不过期,0 表示立即过期
      'OPTIONS': {
            'MAX_ENTRIES': 1000,# 最大缓存条目数
            'CULL_FREQUENCY': 3,# 当达到 MAX_ENTRIES 时删除 1/CULL_FREQUENCY 的缓存
      },
      'KEY_PREFIX': 'myapp_',# 所有缓存键的前缀
      'VERSION': 1,# 默认缓存版本
    }
}支持的缓存后端
# 内存缓存(开发环境常用)
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'

# 文件系统缓存
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache'
'LOCATION': '/var/tmp/django_cache'

# 数据库缓存
'BACKEND': 'django.core.cache.backends.db.DatabaseCache' # python manage.py createcachetable # table_name 是配置中 LOCATION 的值
'LOCATION': 'my_cache_table'

# Memcached
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
'LOCATION': '127.0.0.1:11211'

# Redis(需要 django-redis 包)
'BACKEND': 'django_redis.cache.RedisCache'
'LOCATION': 'redis://127.0.0.1:6379/1'2、缓存API使用

2.1 常见语法

from django.core.cache import cache

# 设置缓存
cache.set('my_key', 'hello, world!', 30)# 缓存30秒

# 获取缓存
value = cache.get('my_key')
print(value)# 输出: hello, world!

# 如果键不存在,返回默认值
value = cache.get('my_key', 'default_value')

# 添加缓存(仅当键不存在时)
cache.add('add_key', 'new_value')

# 获取或设置缓存
value = cache.get_or_set('my_key', 'default_value', 30)

# 删除缓存
cache.delete('my_key')

# 清空所有缓存
cache.clear()

# 自增/自减(针对数字)
cache.set('num', 1)
cache.incr('num')# 2
cache.decr('num')# 1

# 设置多个值
cache.set_many({'a': 1, 'b': 2, 'c': 3})

# 获取多个值
values = cache.get_many(['a', 'b', 'c'])# {'a': 1, 'b': 2, 'c': 3}

# 删除多个值
cache.delete_many(['a', 'b', 'c'])2.2 基本使用

2.2.1 缓存数据库查询结果

from django.core.cache import cache
from myapp.models import Product

def get_popular_products():
    # 尝试从缓存获取
    cache_key = 'popular_products'
    products = cache.get(cache_key)
   
    if products is None:
      # 缓存中没有,从数据库获取
      products = list(Product.objects.filter(
            is_popular=True
      ).select_related('category')[:10])
      
      # 存入缓存,1小时过期
      cache.set(cache_key, products, 60 * 60)
   
    return products2.2.2 缓存模板渲染结果

from django.core.cache import cache
from django.template.loader import render_to_string

def get_rendered_template(context):
    cache_key = f'rendered_template_{hash(str(context))}'
    rendered = cache.get(cache_key)
   
    if rendered is None:
      # 渲染模板
      rendered = render_to_string('my_template.html', context)
      
      # 存入缓存
      cache.set(cache_key, rendered, 60 * 30)# 30分钟
   
    return rendered3、视图缓存

from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator
from django.views import View
from django.http import HttpResponse
import time

# 函数视图缓存
@cache_page(60 * 15)# 缓存15分钟
def my_view(request):
    # 模拟耗时操作
    time.sleep(2)
    return HttpResponse("This content is cached for 15 minutes.")

# 基于类的视图缓存
class MyCachedView(View):
    @method_decorator(cache_page(60 * 5))# 缓存5分钟
    def dispatch(self, *args, **kwargs):
      return super().dispatch(*args, **kwargs)
   
    def get(self, request):
      time.sleep(2)
      return HttpResponse("Cached class-based view.")3、模板片段缓存

{% load cache %}


{% cache 500 sidebar %}
   
      
      <h3>Popular Posts</h3>
      <ul>
            {% for post in popular_posts %}
                <li>{{ post.title }}</li>
            {% endfor %}
      </ul>
   
{% endcache %}


{% cache 500 footer request.user.username %}
    <footer>
      
      <p>User: {{ request.user.username }}</p>
    </footer>
{% endcache %}4、其他

4.1 多个缓存后端

# settings.py

CACHES = {
    'default': {# 默认缓存,通常使用速度较快的内存型缓存
      'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
      'LOCATION': 'unique-snowflake',
      'TIMEOUT': 300,# 全局默认缓存时间(秒)
      'OPTIONS': {
            'MAX_ENTRIES': 1000,# 最大缓存条目数
            'CULL_FREQUENCY': 3,   # 当缓存数达到MAX_ENTRIES时,删除1/CULL_FREQUENCY的缓存
      }
    },
    'special': {# 另一个缓存配置,例如使用文件缓存
      'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
      'LOCATION': '/var/tmp/django_special_cache',# 缓存文件存放目录
      'TIMEOUT': 600,# 此缓存后端的默认超时时间
    }
    }
}4.1.1 使用caches字典

django.core.cache模块提供了一个caches字典,通过缓存的别名(你在 CACHES中定义的键)来获取特定的缓存后端实例
from django.core.cache import caches

def my_view(request):
    # 获取别名为 'special' 的缓存后端
    special_cache = caches['special']
   
    # 使用该缓存进行操作
    value = special_cache.get('my_key')
    if value is None:
      value = get_expensive_data()# 计算或获取昂贵的数据
      special_cache.set('my_key', value, timeout=300)# 缓存5分钟
   
    # 同样,可以使用 'redis' 缓存
    redis_cache = caches['redis']
    redis_cache.set('redis_key', 'some_value')4.1.2 使用 using参数

许多 Django 的内置缓存工具(如 cache_page装饰器)和低级缓存 API 都支持 using参数来指定缓存别名。
from django.views.decorators.cache import cache_page

@cache_page(60 * 15, cache='special')# 使用 'special' 缓存后端,缓存15分钟
def my_special_view(request):
    # ... 视图逻辑
    return HttpResponse("This view uses the 'special' cache.")4.1.3 故障转移与降级

当缓存不可用时,应用应能继续运行
from django.core.cache import caches
from django.core.cache.backends.base import InvalidCacheBackendError

def get_data_safely(key):
    try:
      # 首先尝试从 Redis 获取
      return caches['redis'].get(key)
    except (InvalidCacheBackendError, ConnectionError) as e:
      # 如果 Redis 不可用,回退到本地内存缓存或数据库
      logger.warning(f"Redis cache failed: {e}, falling back to default.")
      data = caches['default'].get(key)
      if data is None:
            data = get_data_from_db(key)
            caches['default'].set(key, data, timeout=60)
      return data4.2 缓存版本控制

Django底层的缓存框架原生支持版本控制。当设置或获取缓存值时,你可以提供一个版本号。缓存系统会存储该版本号,并且在检索时,只有当请求的版本号与缓存值的版本号完全匹配时,数据才会被返回。
from django.core.cache import cache

cache.set('my_key', 'some_value', timeout=None, version=2)
# 获取版本 2 的缓存值
cache.get('my_key', version=2)# 返回 'some_value'

# 获取版本 1 的缓存值(如果存在)
cache.get('my_key', version=1)# 返回 None,因为版本不匹配

# 增加缓存键的版本号(例如当数据结构发生变化时)
cache.incr_version('my_key', version=2)# 将 'my_key' 的版本从 2 增加到 3

cache.get('my_key', version=3)# 返回 some_value

cache.get('my_key', version=2)# 返回 None

# 删除特定版本的缓存值
cache.delete('my_key', version=2)
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: Django缓存