Caching is the process of storing frequently accessed data in a temporary storage location (cache) to improve performance. By caching data, you can avoid repetitive database queries or expensive computations, significantly reducing response times and improving the scalability of your application.
In Django, caching provides a flexible system for storing and retrieving data at various levels of your application, whether it’s for views, templates, or database queries. Caching helps to prevent redundant work by keeping the results of expensive operations and using them when needed.
Django’s caching framework provides a simple API for storing and retrieving data in a cache. It supports multiple cache backends and is highly customizable to suit different needs.
Django supports several cache backends, which determine where the cached data will be stored. You can configure the cache backend in the Django settings.
Memory-based Cache (default)
This backend stores cache data in the memory of the server running Django. It is very fast but not suitable for large-scale applications or multi-server environments.
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}
Filesystem-based Cache
This backend stores cache data on the local filesystem. It is slower than memory cache but persists between restarts.
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/cache/django', # Path where cache files are stored
}
}
Redis Cache
Redis is a high-performance, in-memory key-value store. It is commonly used for caching in distributed systems.
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1', # Redis server location
}
}
Memcached
Memcached is a memory-based caching system designed for high-performance applications.
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211', # Memcached server location
}
}
Django’s caching framework allows you to configure various cache parameters in the settings. You can specify the cache timeout, cache key prefixes, and other settings based on your needs.
Example configuration for memory cache with a timeout setting:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'TIMEOUT': 3600, # Cache timeout in seconds (1 hour)
}
}
Django allows you to cache entire views using the cache_page
decorator or the CacheMiddleware
. These methods cache the full HTML response of a view to improve performance, especially for views with static content.
cache_page
DecoratorThe cache_page
decorator caches the output of a view for a specified amount of time. When the view is accessed, the cached version is returned if it hasn’t expired.
from django.views.decorators.cache import cache_page
from django.shortcuts import render
@cache_page(60 * 15) # Cache the view for 15 minutes
def my_view(request):
return render(request, 'my_template.html')
my_view
for 15 minutes. After the cache expires, Django will regenerate the response and store it again.CacheMiddleware
can be added to the MIDDLEWARE
setting to cache the output of all views automatically. It works based on the cache settings and can be configured for specific URLs.
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
UpdateCacheMiddleware
first and FetchFromCacheMiddleware
second to handle the caching logic properly.Django also supports caching fragments of templates, allowing you to cache only parts of a page. This can be useful when parts of the page change frequently, but other sections remain static.
{% endraw %}{% cache %}
Template TagThe {% endraw %}{% cache %}
tag can be used to cache specific sections of a template. You specify a cache key and a timeout. The block of template code inside the tag will be cached for the specified duration.
{% endraw %}{% load cache %}
{% endraw %}{% cache 600 my_cache_key %}
<h1>Latest News</h1>
<ul>
{% endraw %}{% for article in articles %}
<li></li>
{% endraw %}{% endfor %}
</ul>
{% endraw %}{% endcache %}
{% endraw %}{% cache %}
tag for 10 minutes. After 10 minutes, the cache will expire, and Django will re-render the block.my_cache_key
can be any unique string to identify the cached block.Django provides a low-level caching API that allows you to store and retrieve arbitrary data from the cache. This is useful for caching items like database query results or computations.
cache.set()
and cache.get()
cache.set(key, value, timeout=None)
stores data in the cache.cache.get(key)
retrieves data from the cache.from django.core.cache import cache
# Store data in the cache for 1 hour
cache.set('my_key', 'my_value', timeout=3600)
# Retrieve data from the cache
value = cache.get('my_key')
my_key
is in the cache, cache.get('my_key')
will return its value; otherwise, it will return None
.cache.delete()
and cache.clear()
cache.delete(key)
removes a specific cache key.cache.clear()
clears all cached data.# Delete a specific cache key
cache.delete('my_key')
# Clear all cache data
cache.clear()
cache.delete()
is used to remove a specific cached item, while cache.clear()
wipes all cached data from the backend.Django supports cache versioning, allowing you to store different versions of the cache for the same key. This can be useful when the cache content changes but you want to maintain different versions for various purposes.
You can use a version number when setting or retrieving cache data:
cache.set('my_key', 'my_value', version=1)
value = cache.get('my_key', version=1)
version
parameter allows you to store and retrieve different versions of the same cache key.In addition to using the {% endraw %}{% cache %}
tag for template-level caching, you can also use Django’s cache.get()
and cache.set()
methods within your views to pass cached data into templates.
from django.core.cache import cache
from django.shortcuts import render
def my_view(request):
cached_data = cache.get('my_cached_data')
if not cached_data:
cached_data = compute_expensive_data()
cache.set('my_cached_data', cached_data, timeout=600)
return render(request, 'my_template.html', {'cached_data': cached_data})
Cache invalidation refers to the process of clearing or updating cached data when the underlying data changes. There are various strategies to handle cache invalidation, such as:
Django doesn’t provide built-in automatic cache invalidation for model changes, so you often need to handle it yourself, especially in cases where the data changes frequently.
cache.delete('my_key') # Manually invalidating cache after data change