How to Cache Django REST Framework with 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
When 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.