在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')
# 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'
}
}
根据@Tisho的回答,我通过
解决了这个问题decorators.py
文件views.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
对于已登录的用户,它会为未登录的用户缓存页面(或为缓存页面提供服务),它只会为他们提供常规视图,该视图使用@login_required
进行修饰并需要它们登录。
答案 0 :(得分: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
然后在视图上使用它:
@cache_on_auth(60*60)
def myview(request)
然后,生成的cache_key将如下所示:
cache key:
views.decorators.cache.cache_page._auth_False_.GET.123456.123456
如果用户已通过身份验证,则
cache key:
views.decorators.cache.cache_page._auth_True_.GET.789012.789012
如果用户未经过身份验证。
答案 1 :(得分:2)
如果@Tisho答案中的@wrap装饰器让你的大脑受到伤害,或者显式解决方案比隐式解决方案更好,这里有一个简单的程序方式来提供不同的缓存结果:
from django.views.decorators.cache import cache_page
def index(request):
"""
:type request: HttpRequest
"""
is_authenticated = request.user.is_authenticated()
if is_authenticated:
return render_user(request)
else:
return render_visitor(request)
@cache_page(5, key_prefix='user_cache')
def render_user(request):
print 'refreshing user_cache'
return render(request, 'home-user.html', {})
@cache_page(10, key_prefix='visitor_cache')
def render_visitor(request):
print 'refreshing visitor_cache'
return render(request, 'home-visitor.html', {})
答案 2 :(得分:0)
如果您希望对缓存功能进行微调,我建议不要使用缓存中间件。
然而,如果你想坚持保留它,你可以尝试类似的东西(不是说它会按原样运作,但是类似于它):
@never_cache
def dynamic_index(request):
# do dynamic stuff
def cached_index(request):
return dynamic_index(request)
@never_cache
def index(request):
if request.user.is_authenticaded():
return cached_index(request)
return dynamic_index(request)
最糟糕的情况是,您可以使用cache.set('view_name',template_rendering_result)和cache.get来手动缓存HTML。
答案 3 :(得分:-1)
我知道这是一个非常老的问题,但是我们有一个新的解决方案。
您可以使用装饰器cache_control作为private
传递True
来保护数据。