DEV Community

Hasanul Islam
Hasanul Islam

Posted on • Edited on

Caching in Django REST Framework: Memcached

Caching something is to save the result of an expensive calculation so that we don’t have to perform the calculation next time. We will discuss the caching in Django REST framework step by step:

Caching Concept

This is the pseudocode of the general caching concept:

get data from the cache using a key
if the key is in the cache:
    return the cached data
else:
    generate data
    save the generated data in the cache with a key(for next time)
    return the generated data
Enter fullscreen mode Exit fullscreen mode

Setting up the Memcached :

Install Memcached :

We will install Memcached using docker image.

docker run -d memcached -p 11211:11211 -m 64
Enter fullscreen mode Exit fullscreen mode

This would set the Memcached server to use 64 megabytes for storage running at 11211 port.

Install a Python Client :

We will install pylibmc, a python client to communicate with the Memcached server. But at first, we need to install the required dependencies of pylibmc,

For ubuntu or ubuntu-based docker image,

sudo apt-get install libmemcached-dev zlib1g-dev
Enter fullscreen mode Exit fullscreen mode

For MacOS,

brew install libmemcached
Enter fullscreen mode Exit fullscreen mode

Then install the PyPI package,

pip install pylibmc
Enter fullscreen mode Exit fullscreen mode

Adding Cache Config in settings.py :

CACHE_HOST='127.0.0.1'
CACHE_PORT=11211
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': f'{CACHE_HOST}:{CACHE_PORT}',
    }
}
Enter fullscreen mode Exit fullscreen mode

Caching API Response :

Suppose, We have a user app. We will have the following functionalities:

  • We will implement caching at user details API /api/user/{id}/.
  • Any request at this API will try to get from the cache. If no cached data exists for a user_id, user details data will be fetched from Database.
  • Any change or deletion on the User object will invalidate the cache. The following is the user details API,
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from django.core.cache import cache

from apps.user.models import User
from apps.user.serializers import UserSerializer

class UserViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def retrieve(self, request, pk=None):
        cache_key = f"user_details_{pk}"

        data = cache.get(cache_key)
        if data:
            return Response(data)

        response = super().retrieve(request, pk=pk)
        cache.set(cache_key, response.data)
        return response
Enter fullscreen mode Exit fullscreen mode

Invalidating Cached Data :

We will invalidate the cached data using django signal.

Creating Signal Receivers :

We will add the following lines in user/signals.py,

def _invalidate_cached_data(user_id):
    cache_key = f"user_details_{pk}"
    cache.delete(cache_key)


def user_post_save_handler(sender, instance, created, **kwargs):
    if not created:
        _invalidate_cached_data(instance.id)


def user_post_delete_handler(sender, instance, **kwargs):
    _invalidate_cached_data(instance.id)
Enter fullscreen mode Exit fullscreen mode

Connecting Receivers with Signals :

We will add the following line at user/apps.py inside user app,

from django.apps import AppConfig
from django.db.models.signals import post_save, post_delete


class UserAppConfig(AppConfig):
    name = "apps.user"

    def ready(self):
        from apps.user.models import User
        from apps.user.signals import (
            user_post_delete_handler,
            user_post_save_handler,
        )

        post_save.connect(user_post_save_handler, sender=User)
        post_delete.connect(user_post_delete_handler, sender=User)
Enter fullscreen mode Exit fullscreen mode

Changing default_app_config :

We will add the following line at user/__init__.py in user app.

default_app_config = "apps.user.apps.UserAppConfig"
Enter fullscreen mode Exit fullscreen mode

Feel free to leave a comment.

Top comments (0)