升级Django 1.4到1.6后保存对象时出现列表索引超出范围错误
我最近把我的项目从1.4升级到了1.6,解决了一些过时的问题后,又遇到了一个我无法解决的新问题。
每次我尝试保存一个新对象或者编辑一个已有对象时,都会出现一个叫做 list index out of range
的错误。我明白这个错误的意思,但不太清楚django是怎么给 obj
赋值的,为什么它应该在 obj[3]
这个位置有值。错误追踪信息让我看到了这里: django/contrib/messages/storage/cookie.py 在 process_messages,行38
完整的错误追踪信息:
Traceback:
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
201. response = middleware_method(request, response)
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/middleware.py" in process_response
23. unstored_messages = request._messages.update(response)
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/base.py" in update
140. messages = self._loaded_messages + self._queued_messages
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/base.py" in _loaded_messages
91. messages, all_retrieved = self._get()
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/fallback.py" in _get
24. messages, all_retrieved = storage._get()
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py" in _get
70. messages = self._decode(data)
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py" in _decode
154. return json.loads(value, cls=MessageDecoder)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py" in loads
339. return cls(encoding=encoding, **kw).decode(s)
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py" in decode
49. return self.process_messages(decoded)
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py" in process_messages
41. return [self.process_messages(item) for item in obj]
File "/Users/user/Development/virtual_environments/demo/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py" in process_messages
38. print 'OBJECT 3: {0}'.format(obj[3])
这是来自 cookies.py 的代码。问题出在尝试获取 obj[3]
上。
当前 obj
的值是: [u'__json_message', 20, u'The Player "Goodman" was changed successfully.']
class MessageDecoder(json.JSONDecoder):
"""
Decodes JSON that includes serialized ``Message`` instances.
"""
def process_messages(self, obj):
if isinstance(obj, list) and obj:
if obj[0] == MessageEncoder.message_key:
if obj[1]:
print obj
print 'OBJECT 3: {0}'.format(obj[3])
obj[3] = mark_safe(obj[3])
return Message(*obj[2:])
return [self.process_messages(item) for item in obj]
if isinstance(obj, dict):
return dict([(key, self.process_messages(value))
for key, value in six.iteritems(obj)])
return obj
def decode(self, s, **kwargs):
decoded = super(MessageDecoder, self).decode(s, **kwargs)
return self.process_messages(decoded)
1 个回答
1
这个错误是因为“messages”这个cookie的格式发生了变化,导致Django 1.6无法读取Django 1.4的消息cookie。
Django 1.5修复了这个问题,使它可以支持两种格式,但这个修复在Django 1.6中还没有(还没加进去)。
我已经报告了一个问题。
同时,你可以使用下面的中间件来删除旧格式的cookie:
from django.contrib.messages.storage.cookie import CookieStorage
class FixMessageMiddleware(object):
"""
The message cookie format has changed from Django 1.4 to
Django 1.5. Django 1.5 probably supported both formats,
but if you move from 1.4.x to 1.6.x directly, you will run into
an IndexError:
Exception Type: IndexError
Exception Value:
list index out of range
Exception Location: (...) django/contrib/messages/storage/cookie.py in process_messages, line 37
This small piece of middleware will track those cookies and destroy
them (leaving new-style in tact)
https://code.djangoproject.com/ticket/22426
DISCLAIMER:
This middleware will not attempt to rewrite the messages! You may
miss important notifications because of this!
"""
def process_request(self, request):
data = request.COOKIES.get("messages")
storage = CookieStorage(request)
try:
storage._decode(data)
except IndexError:
del request.COOKIES['messages']
我还在博客上写过关于这个问题的内容(上面的中间件就是来自这里)。