python - Django unicode 连接

标签 python django encoding

unicode和字符串编码还是让我有些头疼。 我关注了this问题/答案能够向消息添加特殊字符 (äÄÜ..)。

对于以下结构,我很难理解为什么版本 2 有效而版本 1 无效。

我的模型:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

class Project(models.Model):
    """
    Representation of a project
    """

    name = models.CharField(max_length=200)

    def __unicode__(self):
            return '%s ' % (self.name)

版本 1:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

def print_project(self, project):
        project_prefix = "Project: "
        print (project_prefix + str(project))

版本 2:

 # -*- coding: utf-8 -*-

def print_project(self, project):
        project_prefix = "Project: "
        print (project_prefix + str(project))

如您所见,唯一的区别是我执行了 from __future__ import unicode_literals 导入。抛出的错误如下:

'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

最佳答案

__future__ 语句之后,您的文字不是 str 对象,而是 unicode 对象。这就是声明的全部要点。 __future__ 中对此描述得不太好。文档或 PEP 3112他们所指的(考虑到字符串文字现在是 Unicode,它大部分时间都在讨论如何编写 Python 2 风格的 bytes 对象)。但这就是它的作用。

您可以在交互式解释器中对此进行测试:

>>> 'abc'
'abc'
>>> from __future__ import unicode_literals
>>> 'abc'
u'abc'

因此,在版本 2 中,您将两个 str 对象添加在一起,这很容易。但在版本 1 中,您添加了 unicodestr。这是通过使用默认编码(即 ASCII)自动将 str 转换为 unicode 来实现的,但这是行不通的。

<小时/>

解决此问题的最简单方法是使 project 本身成为 unicode:

def print_project(self, project):
    project_prefix = "Project: "
    print (project_prefix + unicode(project))

事实上,无论有没有 __future__ 语句,这都可以工作 - 使用它,project_prefix 已经是 unicode;如果没有它,它是一个 str 并将从 ASCII 解码,但这没关系,因为它 ASCII。

如果您想使用非 ASCII 文字(在 project_prefix 中),并且希望您的代码在使用或不使用 __future__ 语句的情况下工作,则必须手动解码:

def print_project(self, project):
    project_prefix = "Project: ".decode('utf-8')
    print (project_prefix + unicode(project))

(当然,请确保与源文件的编码声明匹配。)

<小时/>

在评论中,您询问:

when using the __future__ import statement do I still have to define the coding at the beginning of the .py file? # -- coding: utf-8 --

简短的回答是肯定的。

我不知道文档是否在任何地方直接涵盖了这一点,但如果你仔细想想,没有其他方法可以工作。

为了将 8 位源代码中的文字解释为 Unicode,Python 编译器必须对它们进行解码。它知道从什么中解码它们的唯一方法是您的编码声明。

另一种看待这个问题的方法是,就字符串文字而言,__future__ 语句使 Python 2 的工作方式与 Python 3 类似,而 Python 3 需要编码声明。

如果您想自己测试一下,请将以下内容复制为 UTF 并将其粘贴到文本文件中。 (请注意,您必须使用不理解编码声明的编辑器才能执行此操作 - 像 emacs 之类的编辑器可能会在保存时将您的 UTF-8 文本转换为 Latin-1!)。

# -*- coding: latin-1 -*-
from __future__ import unicode_literals
print repr('é')

当您运行此命令时,它将打印出 u'\xc3\xa9',而不是 u'\xe9'

如果您不指定编码,Python 3 默认为 UTF-8,而 Python 2.5-2.7 默认为 ASCII,即使使用 unicode_literals 也是如此。因此,您仍然需要编码声明。 (即使在 3.x 中,添加总是安全,而且它也让许多程序员的文本编辑器感到高兴,所以这可能是一个值得保留的习惯,直到我们到达足够远的 future ,没有人记得拉丁语-1 和 Shift-JIS 和 cp1250 等。)

关于python - Django unicode 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17052089/

相关文章:

python - 如何创建具有给定有效数字位数的decimal.Decimal对象?

python - 在数据框之间搜索和查找

python - 没有任何循环的 Scipy 快速一维插值

python - 使用 Bootstrap 和 Django

python - 分而治之以找到列表的最大和子列表

javascript - 错误 : [ng:areq] Argument 'GreetingController' is not a function, 未定义

django - 将模型中的对象列表保存为字段

machine-learning - 如何对不同属性具有多个相同值的数据进行一次性编码?

c# - 对Cookie进行加密编码

email - 内容传输编码 7 位或 8 位