I'm using redis server for caching. Using django-redis package.
Below is my setting file :
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
},
}
}
My view :
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
#method_decorator(cache_page(timeout=None,key_prefix="site1"), name='dispatch')
class ProfileView(APIView):
# With auth: cache requested url for each user for 2 hours
def get(self, request, format=None):
content = {
'user_feed': request.user.get_user_feed()
}
return Response(content)
When set timeout=60 it's working. But when i add timeout=None i'm getting 600 seconds timeout.
Im trying to use Google Cloud CDN to cache Django responses. Django properly sets the cache-control header with the max age, but it is missing the 'public' part of the header.
Basically, currently all cached views have:
cache-control: max-age=3600
But I want:
cache-control: max-age=3600,public
Edit:
My current settings.py have the following for caching:
MIDDLEWARE = [
...
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
...
]
....
CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 3600
CACHE_MIDDLEWARE_KEY_PREFIX = ''
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": os.environ.get('CACHE_URL'),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"IGNORE_EXCEPTIONS": True,
"MAX_ENTRIES": 10000,
}
}
}
So I basically followed https://docs.djangoproject.com/en/3.1/topics/cache/. So I cached the entire site. And for those views which I don't want cached I use #never_cache.
Edit 2:
I could add "public=True" to each view with an annotation but I want a solution for the entire site.
For now I ended up just going for a simple middleware. Though I am open for suggestions.
class PublicCacheMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if response.has_header('Cache-Control') and 'private' not in response.get('Cache-Control'):
response['Cache-Control'] += ',public'
return response
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.
Watch out for the Vary header, that cache_page() takes into account.
Usually, some middlewares may add a Vary header, for example :
CsrfViewMiddleware adds Cookie,
GZipMiddlewareadds Accept-Encoding
LanguageCookieMiddleware may add Accept-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 the Vary: Cookie header is not set in the response.
More info at https://docs.djangoproject.com/en/3.0/topics/cache/#using-vary-headers
Though Django documentation, you can read this:
Django’s cache framework
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
If you need to store a page in the local
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': 'c:/foo/bar',
}
}
But, my recommendation is store the results (database result, assets, etc), as #PVSK show in this thread:
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})
Hm, at first I wondered if you're running into some cache default limitations. You are not using OPTIONS in your CACHE backend definition, so the cache is limited to 300 entries per default.
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': os.environ.get('CACHE_LOCATION','127.0.0.1:11211'),
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}
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.
def process_response(self, request, response):
#...
# Don't cache responses that set a user-specific (and maybe security
# sensitive) cookie in response to a cookie-less request.
if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
return response
# ...
The order of execution of middlewares is top-to-bottom for process_request and bottom-to-top for process_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 like LocaleMiddleware 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).
I'm using template cache with django-redis and it works properly but, although I don't use decorators (like cache_page, cache_control etc..), django is caching automatically every loaded page.
I verified this using redis-cli. This is keys * output after page load:
1) ":1:views.decorators.cache.cache_header..11786bb66822aef24b9fe0dac22e6e4e..."
2) ":1:views.decorators.cache.cache_page..GET.11786bb66822aef24b9fe0dac22e6e4e..."
3) ":1:django.contrib.sessions.cached_db8ss2k5s9jmp42cer0fs1nd..."
I tried to use never_cache on every view and it works but I don't see that as a good solution.
There's a better way?
My configuration is simple
CACHES = {
'default':
{
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://redis_ip:redis_port',
'TIMEOUT': 60
},
}
MIDDLEWARE.PY
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
...
'django.middleware.cache.FetchFromCacheMiddleware',
...]
Thanks to all
Remove UpdateCacheMiddleware and FetchFromCacheMiddleware from your MIDDLEWARE settings. They are meant for per-site caching, so every page is cached when you have those middleware.
So I want to cache some data in mysql and some in memcached.
at the moment I have this In my config file, but i don't know how to write router for cache back end.
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
I use multi databases structure and I know how to write multi database routers.
in settings.py
DATABASE_ROUTERS = ['oceankeys.dbrouter.SphinxRouter','oceankeys.dbrouter.DefaultDbRouter']
Any one know how to make Django caching BACKEND router?
Thanks
I don't believe the Django cache framework can mimic db routing in general.
For the site cache using the cache framework middleware you have to specify the name of the cache in settings.py, e.g.:
CACHE_MIDDLEWARE_ALIAS = "my_cache_alias"
For a page cache you can manually specify the name of the cache in the decorator, e.g.:
#cache_page(60 * 15, cache="my_cache_alias")
def my_view(request):
...
I'm not sure cache routing really makes sense for site and page caching so I don't have a problem with the way this is designed.
Now, for your case where you are using MySQL as a database cache backend you can set it up and make a router as per the Django docs section on database caching. For example, this would be your CACHES setting:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
'my_cache_alias': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
}
}
Then create a router that identifies which cache backend to use for which models. It looks and works exactly like DB router (as you should be able to see from the doc section on database caching and multiple databases) with the exception that it returns a cache alias instead of db alias.
e.g
settings.py
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
},
'myalias':{
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
}
}
views.py
from django.core.cache import caches
cache = caches['myalias']
cache.set('my_key', 'hello, world!', 30)
print cache.get('my_key')
You can see the detail in Django’s cache framework (section:Accessing the cache)