django-缓存的使用

訾安邦
2023-12-01

缓存的使用

HTTP 请求通常是数据库链接,数据处理,和模板渲染的。就处理数据而言,它的开销可比服务一个静态网站大多了。

请求开销在你的网站有越来越多的流量时是有意义的。这也使得缓存变得很有必要。通过缓存 HTTP 请求中 的查询结果,计算结果,或者是渲染上下文,你将会避免在接下来的请求中巨大的开销。这使得服务端的响应时间和处理时间变短。

Django 配备有一个健硕的缓存系统,这使得你可以使用不同级别的颗粒度来缓存数据。你可以缓存单一的查询,一个特定的输出视图,部分渲染的模板上下文,或者整个网站。缓存系统中的内容会在默认时间内被储存。你可以指定缓存数据过期的时间。

这是当你的站点收到一个 HTTP 请求时将会通常使用的缓存框架的方法:

1. 试着在缓存中寻找缓存数据
2. 如果找到了,就返回缓存数据
3. 如果没有找到,就执行下面的步骤:
    1. 执行查询或者处理请求来获得数据
    2. 在缓存中保存生成的数据
    3. 返回数据

redis做为缓存后端的使用

pip install django-redis
这是一个开源的项目,github地址是https://github.com/niwibe/django-redis

缓存配置

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
    "TIMTOUT":300,
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}
设置一些常用的过期时间 给 redis
REDIS_TIMEOUT=7*24*60*60
CUBES_REDIS_TIMEOUT=60*60
NEVER_REDIS_TIMEOUT=365*24*60*60

封装一个基本的操作

from django.conf import settings
from django.core.cache import cache


#read cache user id
def read_from_cache(self, user_name):
    key = 'user:id:'+user_name
    value = cache.get(key)
    if value == None:
        data = None
    else:
        data = json.loads(value)
    return data

#write cache user id
def write_to_cache(self, user_name):
    key = 'user:id:'+user_name
    cache.set(key, json.dumps(user_name), settings.NEVER_REDIS_TIMEOUT)

django的缓存框架的使用

Django 提供了以下几个级别按照颗粒度上升的缓存排列:
Per-site cache:最高级的缓存。它缓存你的整个网站。
]Per-view cache:提供单一视图的缓存。
Template cache:允许你缓存模板片段。
Low-level cache API:提供了最高颗粒度。允许你缓存具体的查询或计算结果。

站点级别的缓存
最简单的方法是使用缓存缓存整个网站。 你需要把'django.middleware.cache.UpdateCacheMiddleware' 和 'django.middleware.cache.FetchFromCacheMiddleware' 添加到你的 MIDDLEWARE_CLASSES 设置里, 如例子所示:

MIDDLEWARE_CLASSES = (
    # 开始位置
    'django.middleware.cache.UpdateCacheMiddleware',
    .......
    # 结束位置
    'django.middleware.cache.FetchFromCacheMiddleware',
)

update'中间件,必须放在列表的开始位置,而fectch中间件,必须放在最后。
updata 中间件只实现了process_response() 方法
fecthc 中间件只实现了process_request() 方法
这样的设置就是和django的整个请求流程有关的:
    当请求到来的时候 需要先经过一些列前面的验证 如果请求没有问题的时候, 到最后的fecthc中间件才开始去缓存中读取,如果读取到数据就从缓存中获取,然后在经过一些列的中间件后 到达uapdata中间件 对缓存中的内容判断是不是需要进行保存  
    这样才能保证完整的请求没有问题
对单点的视图函数的缓存
    默认的缓存的时间为5分钟 可以在settings中设置 TIMEOUT超时时间
    使用的是  django.views.decorator.cache import cache_page
    然后使用装饰器来完成缓存  @cache_page(60*15)
官方文档:说明的:
    given a URL, try finding that page in the cache
    if the page is in the cache:
        return the cached page
    else:
        generate the page
        save the generated page in the cache (for next time)
        return the generated page

    和站点缓存一样,视图缓存与 URL 无关。如果多个 URL 指向同一视图,每个URL将会分别缓存。

    @cache_page(30, key_prefix='index1')  制定缓存的前缀

    # 对视图进行缓存 第一个参数 缓存的时间  第二个参数缓存的前缀 在视图函数设定的 会优先于在settings中设定的
        @cache_page(30, key_prefix='index1')
    def index1(request):
        print('进来1')
        return render(request, 'demo001.html')
对模板片段进行缓存
针对模板片段进行缓存
    <!DOCTYPE html>
    {% load cache %}  # 加载cache
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>整站的缓存</title>
    </head>

    <body>
    <h1>缓存03</h1>
    {% cache 60 h2 request.user %}  # 缓存的这个片段 第一个参数 时间(可以是模板变量 只要能解析成整数就行) 第二个是 变量名(不能是模板变量)  第三个是个用户名 针对不同的用户 缓存不同的简明
        <h2>缓存003</h2>
    {% endcache %}
    </body>

    </html>

    缓存超时可以是模板变量,只要模板变量解析为整数值即可。

站点缓存, 视图缓存 和模板缓存都设定时:

站点缓存会生效 这个和请求的流程有关

底层级别的缓存:

使用底层的cache api  这样可以随意的控制自己的缓存的颗粒度 更加细致的缓存的方式
form django.core.cache import cache

最基本的就是
    set(key, value, timeout)

    get(key)  如果不存在就返回一个None
    不要在你的缓存中存储一个NOne  这样当返回的时候 你不知道 这个是没有命中缓存还是缓存中存储的值

    使用add(key, value)  来增加缓存 如果存在的话 不会去更新缓存
    不存在的话就会去设定这个缓存
    如果你需要知道add()是否在缓存中存储了一个值,你可以检查返回值。
    如果值存储,则返回True,否则返回False。

    def index1(request):
        # 可以这样使用cache
        a = cache.get('a')
        if not a:  # 先去缓存中去获取这个值 如果这个值不存在就去吧这个值存在缓存中
            b = 20
            cache.set('a',b)
            a = b
        print(a)
        return render(request, 'demo001.html')


    cache.set_many({'a':100, 'b': 1000, "c": 300},timeout=5)
    set_many(key, timeout) 也是可以设置过期时间的
    cache.get_many(['a', 'b', 'c'])
    返回的是:# OrderedDict([('a', 20), ('b', 12), ('c', 11)])

     获取到的一个字典可以直接的去进行遍历 取值
     key = cache.get_many(['a', 'b', 'c'])
    for item, value in key.items():
        print(item, value)

   删除缓存
    cache.delete('a')

     cache.delete(['a','b])  删除多个键

     cache.clear()  删除所有的在redis中 不仅仅是在程序中设定的 小小的使用



    使用 cache.incr("a")  加1
        cache.decr("a")  减一
        如果存储的不是一个可以转换为数字的 值 就会包错误的
        Can't convert 'int' object to str implicitly

        如果键不存在就会报错的
        您还可以使用incr()或decr()方法分别递增或递减已存在的键。
        默认情况下,现有高速缓存值将递增或递减1。
        可以通过向增量/减量调用提供参数来指定其他增量/减量值。
        如果您尝试增加或减少不存在的缓存键,则会引发ValueError错误

        incr() / decr()方法不能保证是原子的。
        在那些支持原子递增/递减(最明显的是memcached后端)的后端,
        递增和递减操作将是原子的。然而,
        如果后端本身不提供增量/减量操作,
        则它将使用两步检索/更新来实现。


    如果由缓存后端实现,您可以使用close()关闭与缓存的连接。
    对于不实现close方法的缓存,它是一个无操作
 类似资料: