How to Cache Django REST Framework with Redis

Caching Caching
Django Django
Django REST Framework Django REST Framework
Redis Redis

Django REST Framework is an awesome package that will aid you in writing REST APIs faster with Django and Python. Though Django REST Framework has many strengths, performance out-of-the-box might not be one of them. However, there are many ways to fix that, and one of them is caching. So today, I thought I'd share the basics on how you can use Redis as a key-value store to cache Django ORM queries and Django REST Framework's ModelViewSet.

To follow along in this tutorial you should have Redis, Python, Django and Django REST Framework already installed on your local machine. I have written a previous article on how to install Redis on macOS which should work well as base for most systems.

1. Start your Redis server

As I assume that you have Redis installed locally we can go ahead and start the Redis server by opening up the terminal and running the command redis-server.

redis-server

You can also start the Redis CLI in another tab, as we will use that later to monitor cache requests.

redis-cli

2. Install django-redis

When your Redis server is up and running we can start by installing the django-redis package with pip.

pip install django-redis

3. Connect Django and Redis

To connect Django and redis we need to specify the CACHES in settings.py

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

Specify the settings according to your Redis installation. A default local installation of Redis should be located at redis://127.0.0.1:6379/1

4. Specify Session Engine

We need to specify a session engine in the settings. It's important to do so that Redis does not interfere with the Django Admin Panel and the current session.

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

5. Create a default TTL

While we are at it, it can be wise to sepcify a default TTL, that we later can use for specifing how long our cache is going to stay alive.

CACHE_TTL = 60 * 1

In this case we are setting the cache TTL to 60 minutes.

We can then use the default setting when we apply our cache as such..

@method_decorator(cache_page(CACHE_TTL))

Instead of specifying the time manually for every use-case.

6. Add cache as a method decorator to the ModelViewSet

You can work with your django and Django REST Framework cache in many different ways, but the most generic way would be to add a method decorator to your ModelViewSet. 

from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie
from rest_framework.viewsets import ModelViewSet

class NameofViewSet(ModelViewSet):
   serializer_class = NameofSerializer
   queryset = NameofModel.objects.all()
   lookup_field = 'name_of_lookup_field'
   ### and more..

   @method_decorator(vary_on_cookie)
   @method_decorator(cache_page(60*60))
   def dispatch(self, *args, **kwargs):
      return super(NameofViewSet, self).dispatch(*args, **kwargs)

7. Verify the cache by monitoring Redis requests

Whe you have configured the ModelViewSet it can be wise to monitor your cached request with to get a better understanding of what's going on under the hood.

redis-cli monitor

If you have configured everything corretly the terminal should output "GET" and "SET" requests when visiting pages that are included in the ModelViewSet along the following lines..

1588165654.142617 [1 127.0.0.1:59056] "GET" ":1:name-of-key-prefix:9840453994d48edc5b741fcb8df151e4"
1588165654.295159 [1 127.0.0.1:59056] "SET" ":1:name-of-key-prefix:4762ebda23f09acde56f70412dc10072" "2" "PX" "3600000"

I urge you to use the redis-cli monitor to get a better understanding of how you can set, delete and clear cache with Django and Django REST Framework for specific usecases.

cache.clear()
cache.set()
cache.delete('some-key-prefix')

While the concept of caching might be pretty straight forward. To master it, is another. The more complex your application is, usually the more complex your caching will be. So fall back to the monitor and learn the basic, and don't start caching before your application is close to completion, as caching always adds an extra layer of complexity.

Did You Enjoy the Tutorial?

Consider sending some love to Freddie the creator.

Comments (0)

You need to be logged in to comment..

Topics Mentioned in this Tutorial

Caching
3
0
0
Caching is a process in computing that stores data for future faster reference. The data stored in a cache yield faster result by storing a copy of an original query. Caching can be applied to both software and hardware....
Django
7
0
7
Django is a web application framework written in Python. The framework was crafted by developers for developers to make it easier to build better web applications with less code, Hence  Django's slogan "The web framework for perfectionists with deadlines. Besides being a framework for developers that want to ship to production, Django also sports one of the, if not the best documentation found for any web application framework....
Django REST Framework
6
0
1
Django REST Framework is a powerful package for building REST API's with the Django Web Framework and Python. Django REST Framework comes with a browsable API out of the box, a feature that improves the developer experience dramatically. If you have developed applications with Django before, you will feel right at home as Django REST Framework is model after Django. You can query your database with Django's ORM and that you have come accustomed to, and with ease serialize that data as JSON....
Redis
3
0
1
Redis is an open source in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes with radius queries and streams....