Django Rest Framework:Pickle响应

6
我想要做的是构建一个自定义版本的 cache_page,以便我可以更好地控制缓存键,但即使是最基本的响应缓存也卡住了:
from django.core.cache import cache
from rest_framework import viewsets
from rest_framework.response import Response

from app import models

class BaseViewSet(viewsets.GenericViewSet):
    queryset = models.Items.objects.all()

    def get_queryset(self):
        return models.Items.objects.all()

    def list(self, request, **kwargs):
        response = Response({})
        cache.set('test', response, 10)
        return response

我的settings.py中相关部分设置如下:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning'
}
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": f"redis://127.0.0.1:6729/1",
    },
}

当我尝试调用该端点时,我收到以下信息:
django.template.response.ContentNotRenderedError: The response content must be rendered before it can be pickled.

如果我把这行代码改为:
cache.set('test', response.render(), 10)

我明白了:

AssertionError: .accepted_renderer not set on Response

如果我设置渲染器,它会抱怨接受的媒体类型,然后上下文最终失败并出现“TypeError:'bytes' object is not callable”错误。

尽管API调用本身在没有缓存的情况下工作正常。

cache_page 实际上可以正常工作,所以我知道可以缓存响应,但我无法弄清楚我缺少了什么。


遇到了相同的问题。 - Cameron Sima
2个回答

3
我通过使视图返回django.http.JsonResponse而不是rest_framework.response.Response对象来解决了这个问题。问题在于rest_framework Response是媒体类型无关的,据我所知,它依赖于在视图调用链下方设置渲染器和接受的媒体值,在离开处理程序后进行。由于JsonResponse仅处理json,因此它不必经过这个"内容协商"

0

cache_page

这个能够工作是因为:

if hasattr(response, 'render') and callable(response.render):
            response.add_post_render_callback(lambda r: self.cache.set(cache_key, r, timeout))
        else:
            self.cache.set(cache_key, response, timeout)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接