Caching API Responses With Django And Redis.
Save Bandwidth with Redis.
Hello everyone, caching is essential to make a web app great. In this short article, I’ll guide you through setting up caching for your Django API responses using Redis.
Setup
You can see my article 👇 to set up Django in your system using Docker and more.
Project Structure
First, install the necessary dependencies:
pip install django-redis==5.4.0
.
├── db.sqlite3
├── dj_with_redis
│ ├── asgi.py
│ ├── __init__.py
│ ├── __pycache__
│ ├── redis.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── manage.py
├── pyrightconfig.json
Configuration
views.py
from django.http import JsonResponse
def dummy_view(request):
print("Inside Dummy View")
return JsonResponse({
"message": "Dummy View."
})
urls.py
from django.urls import path
from dj_with_redis.views import dummy_view
urlpatterns = [
path("", dummy_view, name="dummy_view")
]
settings.py
Update the settings.py
to configure the cache:
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://localhost:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient"
},
}
}
Initial Test
When you request the homepage, you get the following response:
{"message": "Dummy View."}
And in the logs, you see:
Inside Dummy View
[07/Aug/2024 14:55:31] "GET / HTTP/1.1" 200 26
Inside Dummy View
[07/Aug/2024 14:55:31] "GET / HTTP/1.1" 200 26
Notice that the view is being called every time. Let’s fix this by implementing Redis caching.
Implementing Redis Cache
Create a redis.py
file in the same directory as views.py
:
import json
from functools import wraps
from django.core.cache import caches
from django.http import JsonResponse as Response
redis_client = caches['default'].client
class Cache(object):
@classmethod
def get(cls, key):
value = redis_client.get(key)
if isinstance(value, bytes):
value = value.decode()
return value
@classmethod
def set(cls, key, value, ttl=0):
redis_client.set(*[key, value, ttl])
@classmethod
def cache_api_response(
cls,
key=None,
timeout=60*60,
status_code=200,
):
"""Decorator can cache the response of an api.
Usage:
@action(detail=False, methods=["get"], url_path="dummy-api")
@cache_reponse(timeout=60 * 60)
def view(request):
You can also configure response class to support both Django and DRF Views.
"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
nonlocal key
nonlocal timeout
if not key:
key = func.__name__
cache_data = cls.get(key)
if cache_data:
data = json.loads(cache_data)
return Response(data, status=status_code)
else:
response = func(*args, **kwargs)
data = response.content.decode("utf-8")
cls.set(key, data, timeout)
return response
return wrapper
return decorator
Hint: You can change response.content
to json.dump(response.data)
and similar changes to support DRF views.
Updating the View
Update dummy_view
to use the cache:
from django.http import JsonResponse
from .redis import Cache
@Cache.cache_api_response()
def dummy_view(request):
print("Inside Dummy View")
return JsonResponse({
"message": "Dummy View."
})
Testing the Cache
Now, when you make requests, you will see that the response is cached for 1 hour:
Inside Dummy View
[07/Aug/2024 15:33:12] "GET / HTTP/1.1" 200 26
[07/Aug/2024 15:33:12] "GET / HTTP/1.1" 200 26
[07/Aug/2024 15:33:13] "GET / HTTP/1.1" 200 26
Conclusion
Implementing caching with Redis in Django can significantly improve the performance of your web application by reducing the load on your server and speeding up response times.
If you found it helpful, Leave a 👏 and follow Rahul Beniwal for more upcoming articles.
Other similar articles by me.