问题
在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')
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'
}
}
溶液
根据@Tisho的回答,我通过以下方法解决了这个问题
1.在我的应用程序中创建decorators.py
文件
1.向其中添加以下代码
1.导入views.py
中的函数
1.将它作为装饰器应用到我只想为登录用户缓存的视图中
第1001章:我的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
对于已登录的用户,它会缓存页面(或为他们提供缓存的页面)。对于未登录的用户,它只会为他们提供常规视图,该视图用@login_required
装饰,并要求他们登录。
5条答案
按热度按时间zvokhttg1#
默认的
cache_page
装饰器接受一个名为key_prefix
的变量。但是,它只能作为字符串参数传递。因此,你可以编写自己的装饰器,它将基于is_authenticated
值动态修改这个prefix_key
。下面是一个示例:然后在视图上使用它:
然后,生成的cache_key将如下所示:
如果用户通过身份验证,以及
如果用户未通过身份验证。
ktecyv1j2#
如果@Tisho答案中的@wrap装饰器让您头疼,或者如果显式解决方案比隐式解决方案更好,这里有一个简单的过程化方法来提供不同的缓存结果:
xa9qqrwz3#
如果您希望对缓存能力进行微调,我建议您不要使用该高速缓存中间件。
然而,如果你想坚持保留它,你可以尝试类似的方法(不是说它会按原样工作,而是类似于它的东西):
最坏的情况是,您可以使用
cache.set('view_name', template_rendering_result)
和cache.get
手动缓存HTML。chhkpiq44#
以下是@Tisho的答案的更新版本,适用于Django 3.0(旧版本不再适用,因为Django 3.0中不再支持Python 2):
nzk0hqpo5#
我知道这是一个很老的问题,但我们有一个新的选择来解决这个问题。
您可以使用装饰器cache_control将
private
作为True
传递来保护您的数据。