3 回答
TA贡献1812条经验 获得超5个赞
简单的例子:
def Base:
def _get_data(self):
# get the data eg from database
return self._get_data_native()
def get(self, request, *args, **kwargs):
return Response(self._get_data())
def Cacheable(Base):
def _get_data(self):
# get from cache ...
result = ...
if result is None:
# or from base ...
result = ...
return result
def Derived(Cacheable):
def _get_data_native(self):
# get the data eg from database
...
通过从 Cacheable 继承,您可以在此处包含缓存,因为在此处_get_data被覆盖。
对于这个问题,如果您只想在一个地方添加缓存,则不需要元类或装饰器。
当然,装饰器可用于以更通用的方式包含缓存。
TA贡献1880条经验 获得超4个赞
答案是一个装饰器和一些Django特定的库。
from django.utils.decorators import method_decorator
from django.core.cache import cache
def cached_get(cache_key_func=None):
"""
Decorator to be applied via django.utils.decorators.method_decorator
Implements content-aware cache fetching by decorating the "get" method
on a django View
:param cache_key_func: a function of fn(request, *args, **kwargs) --> String
which determines the cache key for the request
"""
def decorator(func):
def cached_func(request, *args, **kwargs):
assert cache_key_func is not None, "cache_key_function is required"
key = cache_key_func(request, *args, **kwargs)
result = cache.get(key)
if result is None:
return func(request, *args, **kwargs)
return Response(result)
return cached_func
return decorator
@method_decorator(cached_get(cache_key_func=get_cache_key), name="get")
class SomeView(BaseView):
...
def get_cache_key(request):
# do arbitrary processing on request, the following is the naïve melody
key = urllib.urlencode(request.query_params)
return key
因此,解决方案是使用 Django 的内置method_decorator函数,将其第一个参数装饰器应用于装饰类的方法,该方法由第二个参数name, to命名method_decorator。我定义了一个高阶函数,cached_get,它接受另一个函数作为它的参数,并返回一个柯里化函数(闭包,所谓的)。通过调用这个函数get_cache_key(而不是,请注意,调用该函数),我有一个装饰器,它将应用于 .get 方法SomeView。
装饰器本身是一个简单的 Python 装饰器——在这个应用程序中,它是cached_func,而原始的、未装饰的get方法是func。因此,cached_func内容替换SomeView.get,所以当SomeView.get被调用时,它首先检查缓存,但回落到未命中未修饰方法。
我希望这种方法能够在通用适用性与内容感知密钥派生之间取得平衡。
添加回答
举报