在学习Django的过程中,在未使用非英文(Non-English)字符时,Django的Models和MySQL工作的很和谐。但是一旦用 上了非英文字符,例如,我在Django的Admin界面里,添加一项数据时使用到了非英文字符,则会出现错误,Django的错误提示信息包含如下信 息:1366, “Incorrect string value django。

首先考虑是由于Python或者Django对非英文字符支持的问题,因此先查阅Django官方文档中关于字符编码的相关资料(https://docs.djangoproject.com/en/1.3/ref/unicode/)。资料中说到Django中,字符串的编码方式分为两种,一种是Unicode,另外一种是UTF-8,因此我考虑将Django项目的Setting.py中的字符编码统一设置成Unicode,但是立马发现后续文档中讲到(个人翻译):不 要去想着把setting.py中的默认字符编码方式设置成utf-8以外的任意一种编码,因为即使在setting.py中设置了其他的字符编码,你也 没办法完全的控制编码过程,因为具体的编码还取决于该项目实际运行中客户的编码设定(最后一句不是很理解。。。。总之就是在setting.py中设置编 码没啥效果)。并且,在后续的文档中又说到,Django在处理字符串过程中,会统一将字符串转换成Unicode,因此,实际上应该是支持非英文字符的,因此,考虑问题不是出在Django身上,而是出在数据库方面。

接着查看MySQL的编码方式,在MySQL安装目录下的my.ini文件中有这样的配置项:default-character-set。问题就 出在这了,如果是默认情况下的话,可以看见这项配置是”latin”之类的值,也就是拉丁字符。因此,在Django将UTF-8中的非拉丁字符写进到数 据库时,就必然会出现编码问题,因此,解决方案就是统一数据库的编码和Django的编码。因此修改MySQL的编码:修改my.ini文件中的default-character-set和character-set-server两 项配置,均改为UTF-8。但是问题在于,我们已经创建好的数据库的编码方式还是按照原先的Latin的编码方式,因此,解决方法只能是重新创建数据库, 重新创建数据库时,由于我们已经指定了MySQL的编码方式,因此不需要做任何指定,数据库的编码已经是UTF-8。最后重启数据库,解决问题。

而在Django的文档中说到:Django会将任何要处理的字符串进行Unicode编码。但是在实际操作过程中发现,Django实际上使用的还是UTF-8的编码,需要转换才能够变为Unicode编码,甚是不解,留作以后弄明白了再进行记录。

最后做一下总结:

一开始对于编码的理解还不够深刻,有点一知半解,但是经过这个问题,可以得知,Python中字符串的encode和decode方法,其实分别对 应的就是如何存储用户的数据和如何显示用户的数据。encode将一个字符串根据指定的编码格式进行编码(保存),而decode方法则将某种特定的编码 字符串进行解码以显示给用户。使用方式如下:

1 str = '今天'  #Python对其进行UTF-8编码,并保存在内存中
2
3 str #直接输出,可以看到结果'xe4xbbx8axe5xa4xa9',说明是UTF-8的编码
4
5 print str   #乱码,Python根据所属操作系统的默认编码来进行解码,而Win7默认编码是GBK
6 print str.decode("gbk") #结果同上
7
8 print str.decode("UTF-8") #结果正常打印,用相同的格式进行解码

另外,在Django中,提供了简单的转码函数,使用方式如下:

1 str = '今天'
2 #1
3 str = smart_unicode(str,encoding='utf-8',strings_only=False,errors='strict')
4 str #输出u'u4ecau5929',上面这个函数已经将UTF-8编码的字符串转换成了UNICODE编码的字符串
5 #2
6 str = force_unicode(str,encoding='utf-8',strings_only=False,errors='strict')
7 #上面的函数同第一个函数,基本没有差别
8 #3
9 str = smart_str(str,encoding='utf-8',strings_only=False,errors='strict')
10 str #输出'xe4xbbx8axe5xa4xa9',上面这个函数又再次将unicode编码的字符串转为UTF-8编码

用上述的三个函数就可以简单的在UTF-8和Unicode的编码格式中进行转换了,而将UTF-8转换为Unicode的编码的好处在于,Unicode可以直接被Python所识别,因此在使用时不需要再做而外的解码工作,可以直接使用。

关于更详细的说明和URL的编码问题可以参考官方文档:

https://docs.djangoproject.com/en/1.3/ref/unicode/

Python-Django中的字符串编码及写入MySQL数据库时出错的解决方法 | cyfloel0516.

- EOF -