来自Django Cache的TypeError

时间:2015-10-26 22:23:42

标签: python django django-rest-framework pickle

更新:请参阅"更好的解决方案"下方。

这个让我难过。当我调用由Django REST Framework生成的HTML页面时,它可以工作。当我把它称为第二,第三,第四次时,我得到:

[26/Oct/2015 15:14:42]"GET /api/rest/v3/dockets/ HTTP/1.1" 500 92424
Internal Server Error: /api/rest/v3/dockets/
Traceback (most recent call last):
  File "/home/mlissner/.virtualenvs/courtlistener/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 108, in get_response
    response = middleware_method(request)
  File "/home/mlissner/.virtualenvs/courtlistener/local/lib/python2.7/site-packages/django/middleware/cache.py", line 134, in process_request
    response = self.cache.get(cache_key, None)
  File "/home/mlissner/.virtualenvs/courtlistener/local/lib/python2.7/site-packages/django/core/cache/backends/locmem.py", line 54, in get
    return pickle.loads(pickled)
TypeError: __new__() takes exactly 3 arguments (2 given)

与我从Django获得的99%的堆栈跟踪不同,这个跟踪根本没有提到我的代码,而且似乎只是来自Django本身的代码。

我使用的是开发服务器,Django 1.8.7,Django REST Framework 3.2.3和Python 2.7。

我的中间件设置是:

MIDDLEWARE_CLASSES = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
]

我在查看Django REST Framework页面时才看到这一点。有什么想法吗?

我尝试过的事情

  • 升级Django,djangorestframework和djangorestframework-filters。
  • 更改我的CACHE设置,使其使用Redis代替LocMemCache。我认为这可能有所帮助,因为评论中有人说将其改为FileBasedCache有帮助。虽然将其设置为DummyCache,但redis的更改本身并没有帮助。

解决方案

django-redis-cache允许你设置不同版本的泡菜,所以我已经修改了它,因为one link暗示了泡菜版本是相关的。起初,这似乎没有任何效果,但django-redis中的I filed a bug(" PICKLE_VERSION似乎不起作用"),他们很快就修复了。一旦修复,我将PICKLE_VERSION设置为1,问题就解决了。

我还filed a bug in DRF看看是否有更好的方法来深入了解这一点。但是,我不确定错误是在那里,在我的代码中,还是在Django本身。

更好的解决方案

看来,我是处理方法的主人。但好消息是,这是Django Rest框架中的bug,其been fixed已经发布,并将在3.3.2中发布(希望如此)。

2 个答案:

答案 0 :(得分:1)

很容易理解为什么只有在第二次访问页面后才会出现问题。这是因为当您第一次加载页面时,数据从数据源(数据库?)中获取,并写入缓存。之后,每个页面加载将直接命中缓存。

似乎问题与缓存的数据类型有关。在pickle模块中引发异常,当从字符串加载缓存数据时,unpickler会错误地检测数据类型,并调用该类的__new__方法。这就是发生错误的地方。

有些帖子谈论了pickle unload错误,看看它们是否有用:

看起来在挑选元组时存在问题,应用中缓存的数据是否包含元组?

答案 1 :(得分:0)

This was a bug in Django Rest Framework,已修复,已在3.3.2中发布。