Understanding Django's built in cache framework

Deep dive into using Django’s built-in cache framework.

  ·  4 min read

In modern web development loading time of a webpage is fundamental to obtaining and retaining users. There are multiple ways to optimize your site to reduce the load time, one of the ways is by caching web pages that perform heavy queries on the database. This will reduce database hits hence a faster load. So what is caching? 🤷🏾

Caching is storing data in a cache, a temporary storage area that facilitates faster access to data to improve application and system performance.

Django comes with a robust cache system that lets you save dynamic pages so they don’t have to be calculated for each request.

Django offers support to integrate multiple cache backends such as RedisCache, MemCached, DatabaseCache, FileBasedCache, Local-memory Cache.

For this article we will use redis as our cache backend.

Redis is an open-source, in-memory key-value data store used as a database, cache, and message broker.

One of the key features of Redis Cache is its Time To Live (TTL) feature.

Time To Live (TTL) is a feature of Redis Cache that allows users to set an expiration time for their data. This means that the data will be automatically deleted after the expiration time has passed

Setting up cache backend in Django. #

We now set up a backend where our cached data will live — whether it’s the database, filesystem, or Redis which is what we are using today.

Your cache preference goes in the CACHES setting in your settings file as shown below.

Redis #

Redis as cache.

Set up a Redis server. You can start a Redis server locally or on a remote machine.

Starting Redis server with docker.

$ docker run -d -p 6379:6379 redis
#Test if the server is running 👇

# for windows users use wsl to run linux commands

$ sudo apt install redis

$ redis-cli
#Once the Redis terminal opens, type PING the server should respond with PONG which means the server is up and running.

Instead of using Docker, you could also use third-party services such as Redislabs which have a free tier option.

Configure the CACHES setting. #

$ pip install django-redis

Assuming we’ve used Docker to start our Redis server.

# settings.py

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1", # for third-party services use the connection string provided instead
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

The cache backend is now fully set up.

Now we need to identify the data to be cached and set an expiration time for the cached data.

There are 4 ways of performing caching in Django:

Per-site cache #

This is caching your entire site. It’s the simplest way however it’s costly since caching your entire site will lead to more usage of your production infrastructure which leads to high costs.

Implementation.

# settings.py

MIDDLEWARE = [
    "django.middleware.cache.UpdateCacheMiddleware", # add this middleware
    "django.middleware.common.CommonMiddleware",
    "django.middleware.cache.FetchFromCacheMiddleware", # add this middleware
]

CACHE_MIDDLEWARE_SECONDS = 60 * 15 # time the cached data should last
N/B -> Middleware order matters

Per-view cache #

Here we cache the output of individual views. This gives you more control over your cached data when compared to the per-site cache.

from django.views.decorators.cache import cache_page


@cache_page(60 * 15)
def my_view(request):
    ...
#cache_page decorator takes a single argument: the cache timeout, in seconds

Template-fragment caching #

If you’re after even more control, you can also cache template fragments using the cache template tag. To give your template access to this tag, put {% load cache %} near the top of your template.

The {% cache %} template tag takes at least two arguments, cache_timeout in seconds, and the name to give the cache fragment.

Implementation

{% load cache %}
{% cache 500 sidebar %}
    .. sidebar ..
{% endcache %}

Low-level cache API #

We can use this to cache the results of expensive queries instead of caching a whole page.

Check out the docs for more info on low-level cache API.

Django’s cache framework docs.

Thanks for reading 💚

Happy coding 🧑🏾‍💻