我在Django中存储并输出一个ndash字符作为UTF-8时遇到了麻烦 .
我从API获取数据 . 在原始格式中,在文本编辑器中检索和查看时,给定的数据单元可能类似于:
"I love this detergent \u2013 it is so inspiring."
(\ u2013–作为html实体) .
如果我直接从API获得并在Django中显示它,没问题 . 它在我的浏览器中显示为长划线 . 我注意到,如果我尝试在我的视图中对该文本进行一些操作,我必须做 decode('utf-8')
以避免"'ascii' codec can't encode character"错误 . 根据Django调试工具栏,文本将作为"I love this detergent\u2013 it is so inspiring."进入模板 .
然而,当存储到MySQL并通过相同的视图和模板读取输出时,它最终看起来像
"I love this detergent – it is so inspiring"
我的MySQL表设置为 DEFAULT CHARSET=utf8
.
现在,当我通过设置为Utf-8的终端中的MysQl监视器从数据库中读取数据时,它显示为
"I love this detergent – it is so inspiring"
(正确 - 显示ndash)
当我在python shell中使用mysqldb时,这一行是
"I love this detergent \xe2\x80\x93 it is so inspiring"
(这是ndash的正确UTF-8)
However ,如果我运行 python manage.py shell
,然后
In [1]: import myproject.myapp.models ThatTable
In [2]: msg=ThatTable.objects.all().filter(thefield__contains='detergent')
In [3]: msg
Out[4]: [{'thefield': 'I love this detergent \xc3\xa2\xe2\x82\xac\xe2\x80\x9c it is so inspiring'}]
在我看来,Django已经将 \xe2\x80\x93
表示为三个单独的字符,并将其编码为UTF-8为 \xc3\xa2\xe2\x82\xac\xe2\x80\x9c
. 这显示为 - 因为\ xe2似乎是â,\ x80似乎是€等等 . 我已经检查过,这也是它被发送到模板的方式 .
但是,如果使用 decode('utf-8')
解码Python中的长序列,结果是 \xe2\u20ac\u201c
,它也会在浏览器中呈现为 - . 尝试再次解码会产生UnicodeDecodeError .
据我所知,我已经跟着Django suggestions for Unicode(配置了MySQL) .
关于我可能错误配置的任何建议?
附录似乎同样的问题也出现在其他领域或系统中 . 在搜索\ xc3 \ xa2 \ xe2 \ x82 \ xac \ xe2 \ x80 \ x9c时,我在http://pastie.org/908443.txt发现了一个脚本'repair bad UTF8 entities.',也找到了在wordpress RSS导入插件中 . 它只是用 - 替换这个序列 . 不过,我想以正确的方式解决这个问题!
哦,我正在使用Django 1.2和Python 2.6.5 .
我可以使用PHP / PDO连接到同一个数据库并打印出这些数据而不做任何特殊操作,看起来很好 .
2 回答
这似乎是双重编码的情况;我对Python没有太多经验,但请按照http://tahpot.blogspot.com/2005/06/mysql-and-python-and-unicode.html的建议尝试调整MySQL连接设置
我猜测正在发生的是连接是latin1,所以MySQL尝试在存储到UTF-8字段之前再次对字符串进行编码 . 那里的代码,特别是这一点:
可能就是你想要的 .
我在我的php数据插入序列中添加了
set names utf8
,现在在Python shell中,可怕的ndash显示为\ x96 . 当通过Django读取和输出时,这会正确呈现 .关于这一点的一个不寻常的情况是我通过PHP插入数据 . Django自动发出
set names utf8
,如果我通过Django插入和读取数据,那么这个问题就不会出现了 . 我想,PHP使用的是默认的latin1作为一个有趣的说明,在我从PHP读取数据并且它在浏览器中正常显示之前,现在ndash是 ,除非我在读取数据之前调用
set names
.所以,它现在正在运作,我希望我从来不需要了解之前发生的事情!