味酸数据是不透明的,二进制数据,即使您使用协议版本0:
>>> pickle.dumps(data, 0)
'(dp0\nI1\nV\xe9\np1\ns.'
当您尝试存储在TextField
,Django会尝试将该数据解码为UTF8来存储它;这是什么失败,因为这不是UTF-8编码的数据;它是二进制数据,而不是:
>>> pickled_data.decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe9 in position 9: invalid continuation byte
的解决方案是不尝试存储这在TextField
。改为使用BinaryField
:
用于存储原始二进制数据的字段。它仅支持bytes
分配。请注意,该字段的功能有限。例如,无法过滤BinaryField值上的查询集。
你有一个bytes
值(Python的2串是字节字符串,在Python 3更名为bytes
)。
如果你坚持存储在文本字段中的数据,明确它作为解码latin1
;拉丁1编解码器的地图字节单对一个Unicode代码点:
>>> pickled_data.decode('latin1')
u'(dp0\nI1\nV\xe9\np1\ns.'
,并确保你编码一遍又取储存前:
>>> encoded = pickled_data.decode('latin1')
>>> pickle.loads(encoded)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mj/Development/Libraries/buildout.python/parts/opt/lib/python2.7/pickle.py", line 1381, in loads
file = StringIO(str)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 9: ordinal not in range(128)
>>> pickle.loads(encoded.encode('latin1'))
{1: u'\xe9'}
请注意,如果你让这个值转到浏览器并在文本字段中再次返回,浏览器可能会替换该数据中的字符。例如,Internet Explorer将替换\n
字符与\r\n
,因为它假定它处理文本。
不是说你永远应该允许在任何情况下的网络连接接收泡菜的数据,因为that is a security hole waiting for exploitation。
选项3:将unicode数据存储为UTF-8编码的字符串。 –
选项4:改为使用二进制列类型。 –
Pickle数据是* binary *数据。您无法将其编码为UTF-8(文本编码)。 –