# 缓存

  • 缓存的作用:
    • 用户发出一个 HTTP 请求时,网站可能要经过查询数据库、加工数据、渲染前端文件等环节,才能返回 HTTP 响应报文。
    • 如果将中间环节的数据缓存起来,当用户发出一个相同的 HTTP 请求时,不再重复生成数据,而是使用缓存的数据,就可以大幅减少响应耗时。
  • Django 支持在 QuerySet 中缓存数据,避免重复查询数据库,还支持通用的缓存后端。
    • 本文主要介绍如何使用缓存后端来缓存 HTTP 响应报文、Python 对象。

# 缓存后端

Django 支持多种缓存后端:

  • Memcached 内存服务器
  • Django 当前使用的数据库
  • 本地文件
  • 本地内存
    • 默认采用这种方案。
    • 它是线程安全的。但每个进程都会创建一份实例,不能跨进程共享缓存。
    • 它基于 LRU 算法删除缓存的数据。
    • 配置如下:
      CACHES = {
          'default': {
              'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
              # 'LOCATION': 'unique-name',    # 如果存在多个本地内存缓存,则需要给它们指定不同的名称
      
              # 以下参数适用于所有类型的缓存
              # 'TIMEOUT': 300,               # 超时时间
              # 'OPTIONS': {                  # 其它选项
              #     'MAX_ENTRIES': 1000       # 最多缓存多少条数据,超过该数量则删掉旧数据
              # }
          }
      }
      
  • 虚拟缓存
    • 它并不会实际存储数据,主要用于调试。
    • 配置如下:
      CACHES = {
          'default': {
              'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
          }
      }
      
  • 其它自定义的缓存后端

# 缓存视图

  • 在 settings.py 中加入以下配置即可缓存所有 Web 页面:

    MIDDLEWARE = [
        'django.middleware.cache.UpdateCacheMiddleware',    # 最先导入
        ...,
        'django.middleware.cache.FetchFromCacheMiddleware', # 最后导入,用于缓存状态码为 200 的 GET、HEAD 响应报文,会自动设置 Cache-Control 等 Headers
    ]
    
    CACHES = {                                              # 定义缓存
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        }
    }
    
    CACHE_MIDDLEWARE_ALIAS      = 'default'                 # 采用哪个缓存
    CACHE_MIDDLEWARE_SECONDS    = 300                       # 指定每个页面的缓存超时时间,作用于全局所有页面
    CACHE_MIDDLEWARE_KEY_PREFIX = ''
    
  • 可以单独配置某个视图的缓存超时时间:

    from django.views.decorators.cache import cache_page
    
    @cache_page(60)
    def myview(request):
        ...
    

    或者在 urls.py 中配置:

    from django.views.decorators.cache import cache_page
    from . import view
    
    urlpatterns = [
        path('home/', cache_page(60)(view.myview)),
    ]
    

# 缓存 Python 对象

  • 将 Python 对象写入缓存:

    >>> from django.core.cache import cache # 调用当前的缓存实例
    >>> cache.set('key1', 'hello')          # 缓存一对 key、value
    >>> cache.set('key1', 'world', 5)       # 可以自定义超时时间,默认使用全局的超时时间
    
    • 缓存的 key 必须是 str 类型,value 可以是任意 Python 对象。
    • 超时时间的单位为秒。设置为 None 则一直不过期,设置为 0 则不缓存。
  • set() 方法总是会新增或覆盖缓存,而 add() 方法会在指定的 key 不存在时才新增缓存。

    >>> cache.add('key2', 'hello')
    True                                    # 返回值为 True 表示操作成功
    >>> cache.add('key2', 'hello')
    False
    
  • 读取缓存:

    >>> cache.get('key1')                   # 获取一个 key 对于的 value
    'hello world'
    >>> cache.get('key3')                   # 如果指定的 key 不存在,或已超时,则返回值为 None
    >>> cache.get('key3', 'miss')           # 可以指定返回的默认值
    'miss'
    
  • 更新一个 key 的超时时间:

    >>> cache.touch('key1', 10)
    True
    
  • 主动删除缓存:

    >>> cache.delete('key1')
    True
    >>> cache.delete('key1')
    False
    
    • 调用 cache.clear() 会清空所有缓存。
  • 同时操作多个 key :

    >>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
    []
    >>> cache.get_many(['a', 'b', 'c'])
    {'a': 1, 'b': 2, 'c': 3}
    >>> cache.delete_many(['a', 'b', 'c'])