仅为经过身份验证的用户进行Django缓存

Jef*_*eff 21 python django memcached caching heroku

在Django中,如何创建仅对经过身份验证的用户可见的页面的单个缓存版本(对所有用户都相同)?

建立

我希望缓存的页面仅供经过身份验证的用户使用(他们@login_required在视图中使用).所有经过身份验证的用户都可以使用这些页面(例如,无需vary_on_headers根据唯一用户进行设置).

但是,我不希望这些缓存页面对未经过身份验证的用户可见.

到目前为止我尝试过的

  • 页面级缓存(显示用于登录用户的页面到未登录的用户)
  • vary_on_headers查看使用,但我不需要为每个用户单独缓存页面
  • 我检查了模板片段缓存,但除非我感到困惑,否则这将无法满足我的需求
  • 大量搜索(似乎每个人都想反过来)

谢谢!

示例视图

@login_required
@cache_page(60 * 60)
def index(request):
    '''Display the home page'''
    return render(request, 'index.html')
Run Code Online (Sandbox Code Playgroud)

settings.py(相关部分)

# Add the below for memcache
MIDDLEWARE_CLASSES += (
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
)

# Enable memcache
# https://devcenter.heroku.com/articles/memcache#using_memcache_from_python
CACHES = {
    'default': {
        'BACKEND': 'django_pylibmc.memcached.PyLibMCCache'
    }
}
Run Code Online (Sandbox Code Playgroud)

根据@Tisho的回答,我解决了这个问题

  1. decorators.py在我的应用中创建文件
  2. 将以下代码添加到其中
  3. 导入函数 views.py
  4. 将它作为装饰器应用于我想仅为登录用户缓存的视图

decorators.py

from functools import wraps
from django.views.decorators.cache import cache_page
from django.utils.decorators import available_attrs


def cache_on_auth(timeout):
    def decorator(view_func):
        @wraps(view_func, assigned=available_attrs(view_func))
        def _wrapped_view(request, *args, **kwargs):
            if request.user.is_authenticated():
                return cache_page(timeout)(view_func)(request, *args, **kwargs)
            else:
                return view_func(request, *args, **kwargs)
        return _wrapped_view
    return decorator
Run Code Online (Sandbox Code Playgroud)

对于登录用户,它会为未登录的用户缓存页面(或为缓存页面提供服务),它只会为他们提供常规视图,该视图已经过装饰@login_required并需要他们登录.

Tis*_*sho 23

默认cache_page装饰器接受一个名为的变量key_prefix.但是,它只能作为字符串参数传递.所以你可以编写自己的装饰器,它会prefix_key根据is_authenticated值动态修改它.这是一个例子:

from django.views.decorators.cache import cache_page

def cache_on_auth(timeout):
    def decorator(view_func):
        @wraps(view_func, assigned=available_attrs(view_func))
        def _wrapped_view(request, *args, **kwargs):
            return cache_page(timeout, key_prefix="_auth_%s_" % request.user.is_authenticated())(view_func)(request, *args, **kwargs)
        return _wrapped_view
    return decorator
Run Code Online (Sandbox Code Playgroud)

然后在视图上使用它:

@cache_on_auth(60*60)
def myview(request)
Run Code Online (Sandbox Code Playgroud)

然后,生成的cache_key将如下所示:

cache key:   
views.decorators.cache.cache_page._auth_False_.GET.123456.123456
Run Code Online (Sandbox Code Playgroud)

如果用户通过身份验证,并且

cache key:   
views.decorators.cache.cache_page._auth_True_.GET.789012.789012
Run Code Online (Sandbox Code Playgroud)

如果用户未经过身份验证.

  • 感谢你的回答。我承认,我很惊讶 Django 没有“内置”方法来完成此任务。也许他们将来会添加它。 (2认同)