I’m trying to use a Memcached instance of AWS ElastiCache with a Django project. It seems to be caching a view for a user, but if you come in on a different PC, it isn’t cached until called from that PC (or same PC with different browser).
I’m not sure what I’ve got wrong.
Within settings.py
I have
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',
]
I’ve then cached the views using cache_page
path('<str:service_type>/<str:location>/', cache_page(60*60)(views.canonical_search), name="canonical-search"),
How do I cache the site so that the page is cached irrespective of the user?
EDIT
I’ve noticed that it never caches when using the user is logged in.
3
Answers
Watch out for the
Vary
header, thatcache_page()
takes into account.Usually, some middlewares may add a
Vary
header, for example :CsrfViewMiddleware
addsCookie
,GZipMiddleware
addsAccept-Encoding
LanguageCookieMiddleware
may addAccept-Language
meaning that as soon as you have a different Cookie (session), encoding, or language, you have a different version of cache for your page.
As for you case, the
CsrfViewMiddleware
may be the problem, you can add the decorator@csrf_exempt
to your view so that theVary: Cookie
header is not set in the response.More info at https://docs.djangoproject.com/en/3.0/topics/cache/#using-vary-headers
Hm, at first I wondered if you’re running into some cache default limitations. You are not using
OPTIONS
in yourCACHE
backend definition, so the cache is limited to 300 entries per default.The next possible problem, that we also had, is that the cache_key generation takes the full QUERY_STRING into account, so (the
?param=bla
). But you already stated that the url is the same for all users.Next up, as SebCorbin correctly identified, are the potential
Vary
issues.UpdateCacheMiddleware
will never cache a cookie-setting response to a cookie-less request.The order of execution of middlewares is top-to-bottom for
process_request
and bottom-to-top forprocess_response
.I suspect that one of lower middlewares (or the view) is setting a cookie, so you might be able to work around this issue by moving the
'django.middleware.cache.UpdateCacheMiddleware'
below the offending middleware, but you risk loosing features if you don’t move feature-middlewares likeLocaleMiddleware
as well.If your view code is setting cookies you’ll need to switch to the low-level cache API to cache costly operations (or move the cookie logic into a middleware that lives above the
UpdateCacheMiddleware
middleware).Though
Django
documentation, you can read this:Django’s cache framework
If you need to store a page in the local
But, my recommendation is store the results (database result, assets, etc), as @PVSK show in this thread: