在django-redis-cache中使用@cache_page()装饰器

时间:2017-04-03 11:14:55

标签: django caching redis django-redis

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

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中的输出

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"

这是其中一个键下的值

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()装饰者。

为什么在redis数据库中创建这么多密钥?请解释redis数据库中的密钥。 我怎么才能知道这是否有效?

1 个答案:

答案 0 :(得分:1)

cache_page decorator是一个django装饰器,而不是django-redis装饰器。因此,如果你在django中使用像memcached这样的默认缓存,那么cache_page装饰器就会在memcached中创建相同的键。 以下是doc字符串中的装饰器基本代码:

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

  

"""       用于尝试从缓存中获取页面的视图的Decorator       如果页面尚未在缓存中,则填充缓存。       缓存由URL和标头中的一些数据键控。       此外,还有用于区分不同的键前缀       缓存多站点设置中的区域。你可以使用       get_current_site()。域,例如,因为它在Django中是唯一的       项目。       此外,将采用响应的Vary标头中的所有标头       考虑缓存 - 就像中间件一样。       """

因此,它固有地创建了多个密钥,一个用于标头,另一个用于HTTPResponse内容。它根据标题和内容创建密钥,因此标题中的任何更改都会使缓存失效(例如,在变化的标题的情况下),即使在url中具有相同的参数,但在请求标头中的不同内容,您将具有单独的缓存。不同请求标头的示例可以是针对不同登录用户发送关于相同页面的登录信息,或者基于标头中存在的移动/桌面用户代理信息为相同URL提供不同内容。 这是django中的cache key code

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