缓存函数或视图?

Cache function or view?

我想使用 django-rest-framework 缓存。

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

效果很好。

所以实际上我想缓存的不是view而是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)

出现错误TypeError: _wrapped_view() missing 1 required positional argument: 'request'

是否可以为 function 使用缓存??

你可以使用cachetools

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

maxsize 取决于您的要求。

可以向函数参数添加请求:

@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 没有使用 cache-framework 缓存 functions 的 built-in 装饰器。您有三个选择:

A) Python 的 built-in functools.cache 装饰器:

Python的built-infunctools.cache(或functools.lru_cache)装饰器只会缓存在本地内存中,这意味着缓存条目不会在进程之间共享,不要坚持。 (如果你需要 timeout,你可以使用另一个答案中提到的 cachetools 库)

这种技术在某些情况下就足够了(例如,如果您的函数相当便宜),但如果您的函数很昂贵(例如,进行复杂的数据库查询)并且您需要尽量减少缓存未命中,则可能并不理想。

B) Django 的低级缓存 API

您可以直接使用 Django 的 low-level cache apiget()/set() 缓存条目。例如,你会这样做:

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) django-cache-memoize

最简单的选择可能是使用 django-cache-memoize 库,它提供了一个 cache_memoize 装饰器,使用上述 Django 的 low-level 缓存 api 构建。它类似于 cache_page,但用于 functions 而不是 views。然后你可以简单地做:

from cache_memoize import cache_memoize

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

库文档解释了如何自定义缓存键以及其他可用选项。