Skip to content

Conditional Cache Mixin for Django DRF

For a project I’m doing I’m looking at adding a conditional header to bypass cache when an X-No-Cache is present. In my case this allows external system to flush cache when certain conditions are met.

I’ve modified code from Django Rest Framework Extension to allow for such behaviour. There might be a better way to do it, but at the moment the flow of the code is clear to me. It also needs drf-extensions as it’s just an additional mixin that offloads the code to cache_response decorator.

from rest_framework_extensions.cache.decorators import cache_response
from rest_framework_extensions.settings import extensions_api_settings


class BaseCacheResponseMixin(object):
    object_cache_key_func = extensions_api_settings.DEFAULT_OBJECT_CACHE_KEY_FUNC
    list_cache_key_func = extensions_api_settings.DEFAULT_LIST_CACHE_KEY_FUNC


class ConditionalListCacheResponseMixin(BaseCacheResponseMixin):
    @cache_response(key_func="list_cache_key_func")
    def _cached_list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

    def list(self, request, *args, **kwargs):
        if request.META.get("HTTP_X_NO_CACHE") == "1":
            return super().list(request, *args, **kwargs)
        else:
            return self._cached_list(request, *args, **kwargs)


class ConditionalRetrieveCacheResponseMixin(BaseCacheResponseMixin):
    @cache_response(key_func="object_cache_key_func")
    def _cached_retrieve(self, request, *args, **kwargs):
        return super().retrieve(request, *args, **kwargs)

    def retrieve(self, request, *args, **kwargs):
        if request.META.get("HTTP_X_NO_CACHE") == "1":
            return super().retrieve(request, *args, **kwargs)
        else:
            return self._cached_retrieve(request, *args, **kwargs)


class ConditionalCacheResponseMixin(
    ConditionalRetrieveCacheResponseMixin, ConditionalListCacheResponseMixin
):
    pass