Cache function or view?

Viewed 120

I want to use django-rest-framework with cache.

@cache_page(10 * 60)
@api_view(['GET'])
def get_num(request):
    if request.method == "GET":
        res = ["ok"]
        return Response(res)

It works well.

So actually I want to cache not view but function

@cache_page(10 * 60)
def getCalc(num):
    return num * 10


@api_view(['GET'])
def get_num(request):
    if request.method == "GET":
        res = getCalc(request.query_params.get('num'))
        return Response(res)

There comes error TypeError: _wrapped_view() missing 1 required positional argument: 'request'

Is it possible to use cache for function??

3 Answers

you can use cachetools

@cachetools.func.ttl_cache(maxsize=10,ttl=10*6)
def getCalc(num):
    return num * 10

maxsize depends on your requirement.

you can add request to function parameters:

@cache_page(10 * 60)
def getCalc(request, num):
    return num * 10


@api_view(['GET'])
def get_num(request):
    if request.method == "GET":
        res = getCalc(request, request.query_params.get('num'))
        return Response(res)

Django doesn't have a built-in decorator for caching functions using the cache-framework. You have three options:

A) Python's built-in functools.cache decorator:

Python's built-in functools.cache (or functools.lru_cache) decorator will only cache in local memory, which means the cache entries aren't shared between processes, and don't persist. (If you need a timeout, you can use cachetools library as mentioned in another answer)

This technique be sufficient in certain cases (e.g., if your function is fairly inexpensive), but may not be ideal if your function is expensive (e.g., does complex database queries) and you need to minimize cache misses.

B) Django's Low Level Cache API

You can use Django's low-level cache api, and get()/set() cache entries directly. E.g., you would do:

from django.core.cache import cache

def getCalc(num):
    key = f'getCalc__{num}'
    val = cache.get(key)
    
    if val is not None:
        return val

    val = num * 10  # your expensive computation goes here
    cache.set(key, val, 10*60)  # cache timeout: 10 minutes
    return val

C) The django-cache-memoize library

The simplest option may be to use the django-cache-memoize library, which provides a cache_memoize decorator built using the Django's low-level cache api described above. It is analogous to cache_page, but for functions instead of views. Then you can simply do:

from cache_memoize import cache_memoize

@cache_memoize(10*60)
def getCalc(num):
    return num * 10  # your expensive computation goes here

The library documentation explains how you can customize the cache key as well as other available options.

Related