如何缓存Django中所有用户的视图

如何缓存Django中所有用户的视图,django,Django,我正试图在Django项目中使用AWS ElastiCache的Memcached实例。它似乎在为用户缓存视图,但如果您在另一台电脑上访问,则在从该电脑(或使用不同浏览器的同一台电脑)调用之前不会缓存视图 我不确定我做错了什么 在settings.py中 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION':

我正试图在Django项目中使用AWS ElastiCache的Memcached实例。它似乎在为用户缓存视图,但如果您在另一台电脑上访问,则在从该电脑(或使用不同浏览器的同一台电脑)调用之前不会缓存视图

我不确定我做错了什么

settings.py中

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': os.environ.get('CACHE_LOCATION','127.0.0.1:11211'),
    }
}

MIDDLEWARE = [
    'core.middleware.DenyIndexMiddleware',
    'core.middleware.XForwardedForMiddleware',
    'core.middleware.PrimaryHostRedirectMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
    'masquerade.middleware.MasqueradeMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.contrib.sites.middleware.CurrentSiteMiddleware',
    'cms.middleware.user.CurrentUserMiddleware',
    'cms.middleware.page.CurrentPageMiddleware',
    'cms.middleware.toolbar.ToolbarMiddleware',
    'cms.middleware.language.LanguageCookieMiddleware',
    'cms.middleware.utils.ApphookReloadMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
]
然后,我使用
cache\u页面

path('<str:service_type>/<str:location>/', cache_page(60*60)(views.canonical_search), name="canonical-search"),
path('/',cache_页面(60*60)(views.canonical_search),name=“canonical search”),
如何缓存站点,以便缓存页面而不考虑用户

编辑
我注意到,当用户登录使用时,它从不缓存。

注意
Vary
标题,该标题将
cache\u page()
考虑在内

通常,一些中间件可能会添加
Vary
标题,例如:

  • CsrfViewMiddleware
    添加
    Cookie
  • gzimpiddleware
    添加
    接受编码
  • languageCookie中间件
    可以添加
    接受语言
这意味着一旦您有了不同的Cookie(会话)、编码或语言,您的页面就有了不同版本的缓存

对于您的情况,
CsrfViewMiddleware
可能是问题所在,您可以将装饰器添加到视图中,以便在响应中不设置
Vary:Cookie
标题


更多信息请访问

Hm,起初我想知道您是否遇到了一些缓存默认限制。您没有在
缓存
后端定义中使用
选项
,因此每个默认值的缓存限制为300个条目

缓存={
“默认值”:{
'BACKEND':'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION':os.environ.get('CACHE_LOCATION','127.0.0.1:11211'),
“选项”:{
“最大输入”:1000
}
}
}

我们还遇到的下一个可能的问题是,缓存密钥的生成考虑了完整的查询字符串,因此(
?param=bla
)。但是您已经声明url对于所有用户都是相同的

接下来,正如SebCorbin正确指出的,是潜在的
Vary
问题

updateCacheMedware
将永远不会缓存对无cookie请求的cookie设置响应

def过程_响应(自身、请求、响应):
#...
#不要缓存设置了特定于用户(可能还有安全性)的响应
#敏感)响应无cookie请求的cookie。
如果不是request.COOKIES和response.COOKIES,并且具有_vary_头(response,“Cookie”):
返回响应
# ...
对于
处理请求
处理响应
,中间件的执行顺序是从上到下

我怀疑其中一个较低的中间件(或视图)正在设置cookie,因此您可以通过将
'django.middleware.cache.UpdateChemiddleware'
移动到有问题的中间件下方来解决此问题,但如果您不同时移动
LocaleMiddleware
等功能中间件,则可能会丢失功能


如果视图代码正在设置cookie,则需要切换到低级缓存API以缓存代价高昂的操作(或将cookie逻辑移动到
UpdateCacheMddleware
中间件上方的中间件中)。

尽管
Django
文档,您可以阅读以下内容:

如果需要将页面存储在本地

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': 'c:/foo/bar',
    }
}
但是,我的建议是存储结果(数据库结果、资产等),如@PVSK所示:


你好所有用户的URL是否相同?我怀疑是这样,但如果不是这样,问题就出在这里,因为缓存系统是基于每个URL而不是基于每个视图进行缓存的。URL对于所有用户都是相同的。按用户,您是指登录/匿名吗?您的web服务器(nginx/apache)中有任何缓存策略吗?@SebCorbin我使用的是ElasticBeanstalk,但我没有明确设置任何缓存。我不知道ElasticBeanstalk是否有,然后我建议您检查浏览器发送和接收的请求和响应,比较响应的
Vary
头和浏览器发送的头。两者中的
Vary
头都表示
Vary:Accept Language,Cookie,X-Forwarded-Proto,Accept Encoding,用户代理
我不明白这是在告诉meSo什么是的,你有很多可能的变化,我建议你在你正在使用的中间件中搜索
Vary
Cookie
,并尝试调试添加它的中间件。另外,
用户代理
肯定是导致缓存未命中的一个可能原因。一旦我发现哪一个在改变它,我该怎么办?我该如何告诉它不要在头上改变?
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': 'c:/foo/bar',
    }
}
from django.core.cache import cache    
def sample(request):
        cached_data = cache.get_many(['query1', 'query2'])
        if cached_data:
            return render(request, 'sample.html', {'query1': cached_data['query1'], 'query2': cached_data['query2']})
        else:
            queryset1 = Model.objects.all()
            queryset2 = Model2.objects.all()
            cache.set_many({'query1': queryset1 , 'query2': queryset2 }, None)
            return render(request, 'sample.html', {'query1': queryset1 , 'query2': queryset2})