繁体   English   中英

Django 每个用户视图缓存

[英]Django per user view caching

我需要每个用户缓存。 遗憾的是,常规视图缓存不支持基于用户的缓存。

我尝试了这样的模板片段缓存

{% load cache %}
{% cache 500 "mythingy" request.user %}
    ... HTML stuff ...
{% endcache %}

但它慢得要命。

有人知道实现我需要的更快的方法吗?

谢谢!

从 Django >=1.7 开始,在您的视图中使用cache_page和变化的vary_on_cookie装饰器应该可以解决这个问题。

像这样的东西:

from django.views.decorators.vary import vary_on_cookie
from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
@vary_on_cookie
def view_to_cache(request):
    ...

注意一下作为装饰的顺序vary_on_cookie它到达前,应处理cache_page

我找到了解决方案!

这是这个葡萄牙语代码片段,它就像一个魅力!

好消息是我不需要摆弄我的模板代码,但可以使用干净的装饰器!

代码包含在下面

# -*- encoding: utf-8 -*-
'''
Python >= 2.4
Django >= 1.0

Author: eu@rafaelsdm.com
'''
from django.core.cache import cache

def cache_per_user(ttl=None, prefix=None, cache_post=False):
    '''Decorador que faz cache da view pra cada usuario
    * ttl - Tempo de vida do cache, não enviar esse parametro significa que o
      cache vai durar até que o servidor reinicie ou decida remove-lo 
    * prefix - Prefixo a ser usado para armazenar o response no cache. Caso nao
      seja informado sera usado 'view_cache_'+function.__name__
    * cache_post - Informa se eh pra fazer cache de requisicoes POST
    * O cache para usuarios anonimos é compartilhado com todos
    * A chave do cache será uma das possiveis opcoes:
        '%s_%s'%(prefix, user.id)
        '%s_anonymous'%(prefix)
        'view_cache_%s_%s'%(function.__name__, user.id)
        'view_cache_%s_anonymous'%(function.__name__)
    '''
    def decorator(function):
        def apply_cache(request, *args, **kwargs):
            # Gera a parte do usuario que ficara na chave do cache
            if request.user.is_anonymous():
                user = 'anonymous'
            else:
                user = request.user.id

            # Gera a chave do cache
            if prefix:
                CACHE_KEY = '%s_%s'%(prefix, user)
            else:
                CACHE_KEY = 'view_cache_%s_%s'%(function.__name__, user)       

            # Verifica se pode fazer o cache do request
            if not cache_post and request.method == 'POST':
                can_cache = False
            else:
                can_cache = True

            if can_cache:
                response = cache.get(CACHE_KEY, None)
            else:
                response = None

            if not response:
                response = function(request, *args, **kwargs)
                if can_cache:
                    cache.set(CACHE_KEY, response, ttl)
            return response
        return apply_cache
    return decorator

对于使用 django rest 框架的人以及其他人:

def cache_per_user(timeout):
  def decorator(view_func):
    @wraps(view_func, assigned=available_attrs(view_func))
    def _wrapped_view(request, *args, **kwargs):
        user_id = 'not_auth'
        if request.user.is_authenticated:
            user_id = request.user.id

        return cache_page(timeout, key_prefix="_user_{}_".format(user_id))(view_func)(request, *args, **kwargs)

    return _wrapped_view

  return decorator

用法:

@method_decorator(cache_per_user(3600))

以下是不考虑请求参数的已接受解决方案的改进版本。

decorator_of_cache_per_user.py

from django.core.cache import cache as core_cache

def cache_key(request):
    if request.user.is_anonymous():
        user = 'anonymous'
    else:
        user = request.user.id

    q = getattr(request, request.method)
    q.lists()
    urlencode = q.urlencode(safe='()')

    CACHE_KEY = 'view_cache_%s_%s_%s' % (request.path, user, urlencode)
    return CACHE_KEY

def cache_per_user_function(ttl=None, prefix=None, cache_post=False):
    def decorator(function):
        def apply_cache(request, *args, **kwargs):
            CACHE_KEY = cache_key(request)

            if prefix:
                CACHE_KEY = '%s_%s' % (prefix, CACHE_KEY)

            if not cache_post and request.method == 'POST':
                can_cache = False
            else:
                can_cache = True

            if can_cache:
                response = core_cache.get(CACHE_KEY, None)
            else:
                response = None

            if not response:
                response = function(request, *args, **kwargs)
                if can_cache:
                    core_cache.set(CACHE_KEY, response, ttl)
            return response
        return apply_cache
    return decorator

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM