django-redis-cache中@cache_page()装饰器的工作 [英] Working of @cache_page() decorator in django-redis-cache

查看:59
本文介绍了django-redis-cache中@cache_page()装饰器的工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用(尝试)redis作为django应用程序的缓存.这就是我试图做到的方式.

I am using(trying) redis as a cache to my django app. This is how I am trying to do it.

def postview(request):
    post_list = []
    if cache.get("posts") == None:
           post_list = Post.objects.all()
           cache.set("posts", post_list, timeout=None)
    else : 
           post_list = cache.get("posts")
    context = {"post_list" : post_list}
    return render(request, 'post_list.html', context)

@cache_page(60*15, key_prefix="test_cache")
def new(request):
    print("testing")
    return HttpResponse("hello, I am mohammed")

这是redis-cli的输出

This is the output in redis-cli

luvpreet@DHARI-Inspiron-3542:~/test_venv_wrapper/test_redis$ redis-cli
127.0.0.1:6379> select 2 # I have redis db 2 as backend in django settings
OK
127.0.0.1:6379[2]> keys *
1) ":1:views.decorators.cache.cache_page.cache_test.GET.26488770af116d67b33750e5f304aa3e.d41d8cd98f00b204e9800998ecf8427e.en-us.UTC"
2) ":1:views.decorators.cache.cache_header..d314df08d6409ed165873dfa23271c50.en-us.UTC"
3) ":1:posts"
4) ":1:views.decorators.cache.cache_page..GET.d314df08d6409ed165873dfa23271c50.d41d8cd98f00b204e9800998ecf8427e.en-us.UTC"
5) ":1:views.decorators.cache.cache_header..26488770af116d67b33750e5f304aa3e.en-us.UTC"
6) ":1:views.decorators.cache.cache_page..GET.26488770af116d67b33750e5f304aa3e.d41d8cd98f00b204e9800998ecf8427e.en-us.UTC"
7) ":1:views.decorators.cache.cache_header.cache_test.26488770af116d67b33750e5f304aa3e.en-us.UTC"

这是其中一个键下的值,

This is the value under one of the keys,

127.0.0.1> get :1:views.decorators.cache.cache_page.cache_test.GET.26488770af116d67b33750e5f304aa3e.d41d8cd98f00b204e9800998ecf8427e.en-us.UTC
"\x80\x02cdjango.http.response\nHttpResponse\nq\x01)\x81q\x02}q\x03(U\x0e_handler_classq\x04NU\b_headersq\x05}q\x06(U\rlast-modifiedU\rLast-ModifiedU\x1dWed, 05 Apr 2017 10:56:58 GMT\x86U\aexpiresU\aExpiresU\x1dWed, 05 Apr 2017 15:06:58 GMT\x86U\x0ccontent-typeU\x0cContent-TypeU\x18text/html; charset=utf-8\x86U\rcache-controlU\rCache-ControlU\rmax-age=15000\x86uU\b_charsetq\aNU\x11_closable_objectsq\b]U\acookiesq\tcdjango.http.cookie\nSimpleCookie\nq\n)\x81q\x0b}q\x0cbU\x06closedq\r\x89U\n_containerq\x0e]q\x0fU\x14Hello, I am Mohammedq\x10aU\x0e_reason_phraseq\x11Nub."

这是一些序列化的值.

查询集 Post.objects.all()已被缓存,从缓存中获取此对象没有问题.但是我无法理解这个 @cache_page()装饰器.

The queryset Post.objects.all() is cached and I have no problem in getting this from cache. But I am failing to understand this @cache_page() decorator.

为什么在redis数据库中创建这么多密钥?请说明在redis数据库中创建的密钥.我怎么知道这是行不通的?

Why is it making so many keys in the redis database ? Please explain the keys made in the redis database. How can I get to know this is working or not ?

推荐答案

cache_page 装饰器是django装饰器,而不是django-redis装饰器.因此,如果您在django中使用像memcached这样的默认缓存,则cache_page装饰器将在memcached中创建相同的键.这是doc字符串中的装饰器基本代码:

cache_page decorator is a django decorator, not a django-redis decorator. So, if you were using a default cache like memcached in django, the cache_page decorator would have been making the same keys in memcached. Here is the decorator base code along the doc string :

https://github.com/django/django/blob/711123e1cdaf3b08c876c045d8d38decdc7a63d3/django/views/decorators/cache.py#L8

"尝试从缓存中获取页面的视图的装饰器,以及如果页面不在缓存中,则填充缓存.URL和标头中的一些数据为缓存设置了密钥.此外,还有用于区分不同内容的键前缀在多站点设置中缓存区域.您可以使用get_current_site().domain,例如,因为这在Django中是唯一的项目.此外,将采用响应的Vary标头中的所有标头考虑到缓存-就像中间件一样.""

""" Decorator for views that tries getting the page from the cache and populates the cache if the page isn't in the cache yet. The cache is keyed by the URL and some data from the headers. Additionally there is the key prefix that is used to distinguish different cache areas in a multi-site setup. You could use the get_current_site().domain, for example, as that is unique across a Django project. Additionally, all headers from the response's Vary header will be taken into account on caching -- just like the middleware does. """

因此,从本质上讲,它正在创建多个密钥,一个用于标题,另一个用于HTTPResponse内容.它基于标头和内容创建密钥,以便标头的任何更改都会使缓存无效(例如,在标头变化的情况下),即,即使url中的参数相同,但请求标头中的内容不同,您也将拥有单独的缓存.不同请求标头的示例可以是针对不同的登录用户发送有关同一页面的登录信息,也可以基于标头中存在的移动/桌面用户代理信息为相同的url提供不同的内容.这是django中的缓存键代码:

So, inherently it is creating multiple keys, one for headers and other for the HTTPResponse content. It creates the keys based on header and content, so that any change in header invalidates the cache ( for example in case of vary headers ), i.e. even with same parameters in the url, but different content in request-headers you will have seperate caches. Examples of different request-headers can be sending login info about same page for different logged in users, or serving different content for same url based on mobile/desktop user agent information present in headers. Here is the cache key code in django :

def _generate_cache_key(request, method, headerlist, key_prefix):
    """Return a cache key from the headers given in the header list."""
    ctx = hashlib.md5()
    for header in headerlist:
        value = request.META.get(header)
        if value is not None:
            ctx.update(force_bytes(value))
    url = hashlib.md5(force_bytes(iri_to_uri(request.build_absolute_uri())))
    cache_key = 'views.decorators.cache.cache_page.%s.%s.%s.%s' % (
        key_prefix, method, url.hexdigest(), ctx.hexdigest())
    return _i18n_cache_key_suffix(request, cache_key)


def _generate_cache_header_key(key_prefix, request):
    """Return a cache key for the header cache."""
    url = hashlib.md5(force_bytes(iri_to_uri(request.build_absolute_uri())))
    cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
        key_prefix, url.hexdigest())
    return _i18n_cache_key_suffix(request, cache_key)


def get_cache_key(request, key_prefix=None, method='GET', cache=None):
    """
    Return a cache key based on the request URL and query. It can be used
    in the request phase because it pulls the list of headers to take into
    account from the global URL registry and uses those to build a cache key
    to check against.
    If there isn't a headerlist stored, return None, indicating that the page
    needs to be rebuilt.
    """
    if key_prefix is None:
        key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
    cache_key = _generate_cache_header_key(key_prefix, request)
    if cache is None:
        cache = caches[settings.CACHE_MIDDLEWARE_ALIAS]
    headerlist = cache.get(cache_key)
    if headerlist is not None:
        return _generate_cache_key(request, method, headerlist, key_prefix)
    else:
        return None

这篇关于django-redis-cache中@cache_page()装饰器的工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆