首页 文章

Django是否对Unicode(utf-8?)字符串进行双重编码?

提问于
浏览
6

我在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 回答

  • 1

    这似乎是双重编码的情况;我对Python没有太多经验,但请按照http://tahpot.blogspot.com/2005/06/mysql-and-python-and-unicode.html的建议尝试调整MySQL连接设置

    我猜测正在发生的是连接是latin1,所以MySQL尝试在存储到UTF-8字段之前再次对字符串进行编码 . 那里的代码,特别是这一点:

    编辑:使用Python Build 数据库连接时添加以下标志:init_command ='SET NAMES utf8' . 另外在MySQL的my.cnf中设置以下内容:default-character-set = utf8

    可能就是你想要的 .

  • 0

    我在我的php数据插入序列中添加了 set names utf8 ,现在在Python shell中,可怕的ndash显示为\ x96 . 当通过Django读取和输出时,这会正确呈现 .

    关于这一点的一个不寻常的情况是我通过PHP插入数据 . Django自动发出 set names utf8 ,如果我通过Django插入和读取数据,那么这个问题就不会出现了 . 我想,PHP使用的是默认的latin1

    作为一个有趣的说明,在我从PHP读取数据并且它在浏览器中正常显示之前,现在ndash是 ,除非我在读取数据之前调用 set names .

    所以,它现在正在运作,我希望我从来不需要了解之前发生的事情!

相关问题