built-in options are:
-
Memcached - is a memory-based, key-value store for small chunks of data. It supports distributed caching across multiple servers. https://memcached.org/
-
Database - Here, the cache fragments are stored in a database. A table for that purpose can be created with one of the Django's admin commands. This isn't the most performant caching type, but it can be useful for storing complex database queries.
-
Local Memory - The cache is saved on the file system, in separate files for each cache value. This is the slowest of all the caching types, but it's the easiest to set up in a production environment.
-
Dummy - A "dummy" cache that doesn't actually cache anything but still implements the cache interface. It's meant to be used in development or testing when you don't want caching, but do not wish to change your code.
- per-site cach
- per-view cache
- template fragment cache
- low-level cache API
- easiest to implement
# settings.py
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware', # NEW
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware', # NEW
]
-
UpdateCacheMiddleware
comes beforeFetchFromCacheMiddleware
-
add the following too
# settings.py
CACHE_MIDDLEWARE_ALIAS = 'default' # which cache alias to use
CACHE_MIDDLEWARE_SECONDS = '600' # number of seconds to cache a page for (TTL)
CACHE_MIDDLEWARE_KEY_PREFIX = '' # should be used if the cache is shared across multiple sites that use the same Django instance
- almost always start with this when starting to implement caching.
- use the cache_page decorate either on view function or in path
# urls.py
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def your_view(request):
...
# or
from django.views.decorators.cache import cache_page
urlpatterns = [
path('object/<int:object_id>/', cache_page(60 * 15)(your_view)),
]
- Cache is url-based e.g
objec/1
andobject/2
will be cached separately. - prefer implementing the cache on url. Implementing on view makes it difficult to disable the cache on certain scenarios
from django.views.decorators.cache import cache_page
urlpatterns = [
path('object/<int:object_id>/', your_view),
path('object/cache/<int:object_id>/', cache_page(60 * 15)(your_view)),
]
- allows specifying specific areas of a template cache
<!--some_template.html-->
{% load cache %}
{% cache 500 object_list %}
<ul>
{% for object in objects %}
<li>{{ object.title }}</li>
{% endfor %}
</ul>
{% endcache %}
{% cache 500 object_list %}
here cache ttl is 500 seconds. Cache fragment name is object_list
- helps in managing individual objects in the cache by cache key
example
from django.core.cache import cache
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
objects = cache.get('objects')
if objects is None:
objects = Objects.all()
cache.set('objects', objects)
context['objects'] = objects
return context
- ensure you invalidate the cache when objects are added/changed/removed from the db e.g using signals
# signals.py
from django.core.cache import cache
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
@receiver(post_delete, sender=Object)
def object_post_delete_handler(sender, **kwargs):
cache.delete('objects')
@receiver(post_save, sender=Object)
def object_post_save_handler(sender, **kwargs):
cache.delete('objects')
- Test Driven Caching Article - this repo is actually conceived from it.