Django rest framework cache response in list method based on query_params

3.1k Views Asked by At

I am using django rest framework to model api views. I have an API ModelViewSet class which has two action methods: list() and retrieve()

retrieve() method example:

@method_decorator(never_cache)
def retrieve(self, request, *args, **kwargs):
    # /en/api/v1/pair/<parameter> calls this method
    ...
    return Response(some_data)

list() method example:

@method_decorator(cache_page(settings.PAIR_CACHE_LIFETIME))
def list(self, request, *args, **kwargs):
    # /en/api/v1/pair/, /en/api/v1/pair/?name=<parameter> calls this method
    # /en/api/v1/pair/ and /en/api/v1/pair/?name=all - response SHOULD be cached
    # /en/api/v1/pair/?name=random and /en/api/v1/pair/?name=CORRECT_PAIR_NAME - SHOULD NOT be cached
    ...
    return Response(some_data)

When the GET request is sent to /en/api/v1/pair - it call list method which is decorated to cache response. When the GET request is sent to /en/api/v1/pair/ - it calls retrieve method which is decorated to never_cache.

I am adding the feature to return random pair, when GET request is sent to /en/api/v1/pair/?name=random. But as it calls list method, the return is cached for some time and return the same response for a while.

What would be the way NOT to cache response in list() method, when /en/api/v1/pair/?name=random endpoint is called, but it should cache whatever else is called in list method.

Thank you!

1

There are 1 best solutions below

0
On

I did

from django.views.decorators.cache import cache_page 
from django.utils.decorators import method_decorator   

class MyViewSet(viewsets.ModelViewSet):                                                                                                                                                                                            
    serializer_class = MySerializer                                                                                 

    @method_decorator(cache_page(60*5)) # cache for 5 minutes                                                          
    def list(self, request, format=None):                                                                              
        queryset = self.filter_queryset(self.get_queryset())                                                           

        page = self.paginate_queryset(queryset)                                                                        
        if page is not None:                                                                                           
            serializer = self.get_serializer(page, many=True)                                                          
            return self.get_paginated_response(serializer.data)                                                        

        serializer = self.get_serializer(queryset, many=True)                                                          
        return Response(serializer.data)

Note that here the definition of list is the same as the source, i.e. I have not changed it, it is only here to demonstrate how to cache it.