Django 仍然使用 @never_cache 装饰器缓存视图

问题描述 投票:0回答:3

我将 Django 与 Django Rest Framework 和 uWSGI 一起使用。我在带有 pylibmc 后端的服务器上设置了 memcached。我为每个站点缓存配置了 Django,因此每个视图都应该被缓存,除了我使用 @never_cache 装饰器免除的视图。我不明白为什么 Django 仍然尝试缓存我的 API 视图,即使添加了 Django 的 @never_cache 装饰器。我有一个支持草稿模型读写操作的 API。当我使用 UpdateAPIView 进行草稿更新,然后刷新页面时,它仍然显示更新之前的草稿数据。我已经确认它不是浏览器端缓存,因为网络日志显示 200 响应,而不是 304,如果我清除 memcached 并刷新页面,则可以正确返回更新的草稿。

最近,当我将 Django 从 1.8 升级到 1.10 时,就发生了这种情况,大约 15 个 pip 包依赖项、操作系统发行版及其包(因此很难准确找出导致它的原因)。

DRF 检索 API 视图

from django.views.decorators.cache import never_cache

class DraftDetail(generics.RetrieveAPIView):
    queryset = Draft.objects.all()
    serializer_class = DraftSerializer
    permission_classes = (permissions.IsAuthenticated, HasReadWriteAccess)

    @never_cache
    def dispatch(self, *args, **kwargs):
        return super(DraftDetail, self).dispatch(*args, **kwargs)

我也尝试过基于替代类的@method_decorator,但没有变化:

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

@method_decorator(never_cache, name='dispatch')
class DraftDetail(generics.RetrieveAPIView):
    queryset = Draft.objects.all()
    serializer_class = DraftSerializer
    permission_classes = (permissions.IsAuthenticated, HasReadWriteAccess)

设置.py

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': '127.0.0.1:11211',
    }
}
PYLIBMC_MIN_COMPRESS_LEN = 250
# The cache alias to use for storage.
CACHE_MIDDLEWARE_ALIAS = 'default'
# The number of seconds each page should be cached.
CACHE_MIDDLEWARE_SECONDS = 500
CACHE_MIDDLEWARE_KEY_PREFIX = 'app'

MIDDLEWARE_CLASSES = (
    'django.middleware.cache.UpdateCacheMiddleware',
    (...),
    'django.middleware.cache.FetchFromCacheMiddleware',
)

我还在请求标头中设置了 Cache-Control:max-age=0 。

django caching django-rest-framework memcached
3个回答
2
投票

即使您向

dispatch
方法添加装饰器,也应该使用
method_decorator

Django的官方文档说:

类上的方法与独立函数不太一样,因此您不能只将函数装饰器应用于该方法 - 您需要首先将其转换为方法装饰器。

never_cache
装饰器没有任何参数;所以应该不带括号使用。所以也许这有效:

@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
    ....

2
投票

也许

@method_decorator(never_cache)

0
投票

我在 DRF ModelViewset 上遇到了同样的问题,发现它是由范围问题引起的,如this SO answer

中所述

这就是我最初定义视图集的方式,请注意查询集位于类定义中,这意味着它仅运行一次。

class ActivityCategoryViewSet(viewsets.ModelViewSet):
queryset = ActivityCategory.objects.all()
permission_classes = [IsAuthenticatedOrReadOnly, ]

def list(self, request, *args, **kwargs):
    serializer = ActivityCategorySerializer(self.queryset, many=True)
    return Response(serializer.data)

通过将查询集移动到列表方法中解决了缓存问题:

class ActivityCategoryViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticatedOrReadOnly, ]

def list(self, request, *args, **kwargs):
    serializer = ActivityCategorySerializer(ActivityCategory.objects.all(), many=True)
    return Response(serializer.data)
© www.soinside.com 2019 - 2024. All rights reserved.