Django:非ASCII字符

22

我的Django视图/模板无法处理特殊字符。下面的简单视图由于ñ而失败。我收到以下错误:

文件中的非ASCII字符'\xf1'

def test(request):
    return HttpResponse('español')

是否有一些通用设置需要我设置?如果我必须单独处理所有字符串,那就太奇怪了:非美国字母很常见!

编辑 这是对下面评论的回应。它仍然失败了 :(

我按照Gabi建议的方法,在我的视图中添加了编码注释和元信息到我的html中。

现在,上面的例子没有出错,但是ñ显示不正确。

我尝试了return render_to_response('tube/mysite.html', {"s": 'español'})。没有错误,但它不会显示(如果s=hello,则会显示)。页面上的其他信息都显示正常。

我试着将'español'硬编码到HTML中,但失败了:

UnicodeDecodeError 'utf8' codec can't decode byte 0xf.

我尝试在字符串前面加上u:

SyntaxError (unicode error) 'utf8' codec can't decode byte 0xf1

这能帮上忙吗?


你实际遇到的错误是什么?是UnicodeDecodeError吗? - rubayeet
你使用的是哪个版本的Django?不会是0.96吧? - lemonad
你需要确保你的编辑器使用你指定的编码保存文件。 - John La Rooy
7个回答

38

你的脚本开头是否有这段代码:

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

参见:http://www.python.org/dev/peps/pep-0263/

编辑:关于第二个问题,它涉及到HTML编码。将以下内容放在您的HTML页面的头部(您应该将请求作为一个HTML页面发送,否则我认为您将无法正确输出该字符):

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

我根据您的评论更新了问题描述。它仍然无法工作... - dkgirl
返回 HttpResponse('string') 很粗糙...使用包含上述元素的 HTML 模板将会很有用,然后使用 render_to_response('mytemplate.html')。 - Dominique Guardiola
这解决了在代码中使用显式字符串时使用特殊字符的问题。谢谢。 - Leandro Ardissone

17

在views.py文件的顶部插入

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

在你的字符串之前添加“u”

my_str = u"plus de détails"

已解决!


1
你的答案是这个回答和这个回答的结合,但不够完整。最好的方式是编辑其他答案来使它们更完整。如果不能编辑,请至少与其他答案一样完整。 - Chris Wesseling

8

仍然无法正常工作。添加注释(但不包括u)会产生不同类型的错误。现在可以显示该单词,但是ñ被替换为方块或其他奇怪的符号,具体取决于浏览器。当我也包括u时,根本无法工作。我收到“utf8'编解码器无法解码位置0处的字节0xf1”的消息。 - dkgirl

3

在您的 settings.py 文件中,将 DEFAULT_CHARSET 设置为 'utf-8'


3
默认情况下,DEFAULT_CHARSET 被设置为 utf-8。 - Wade Williams
这可能在发布和评论之间的两年中发生了变化。我也冒昧等了两年才说这句话。 - random6174

0
关于编码的事情,除了通过和项目的settings.py文件声明使用UTF-8之外,你当然要尊重你的声明:确保你的文件使用UTF-8编码保存。 原因很简单:你告诉解释器使用特定字符集进行输入输出。 当你没有使用该字符集保存文件时,解释器就会迷失方向。
一些IDE和编辑器默认使用Latin1(ISO-8859-1),这就解释了为什么Ryan的答案可能有效。 虽然这不是对所提出的原始问题的有效解决方案,但可以快速修复。

0

参考来源:https://docs.djangoproject.com/en/1.8/ref/unicode/

如果您的代码只使用ASCII数据,那么可以放心地使用普通字符串,在需要时传递它们,因为ASCII是UTF-8的子集。

不要被误导认为,如果DEFAULT_CHARSET设置为除'utf-8'之外的其他编码,您可以在字节串中使用该其他编码!DEFAULT_CHARSET仅适用于模板呈现(和电子邮件)生成的字符串。Django始终假定内部字节串采用UTF-8编码。原因是DEFAULT_CHARSET设置实际上不在您的控制范围内(如果您是应用程序开发人员)。它在安装和使用您的应用程序的人的控制下 - 如果该人选择了不同的设置,则您的代码仍必须继续工作。因此,它不能依赖于该设置。

在大多数情况下,当Django处理字符串时,它会在执行任何其他操作之前将它们转换为Unicode字符串。因此,作为一般规则,如果您传入一个字节串,请准备好在结果中收到一个Unicode字符串。


0

我和@dkgirl一样遇到了同样的问题,尽管我已经按照这里建议的所有更改进行了更改,但我仍然无法在从我的模板呈现的页面中显示包含ñ的settings.py中定义的常量字符串。

相反,我将python代码中每个实例的"utf-8"替换为上面解决方案中的"ISO-8859-1"(Latin-1)。现在它可以正常工作。

奇怪的是,一切似乎表明utf-8支持ñ(实际上我仍在使用utf-8模板)。也许这只是在旧版Django版本上出现的问题?我正在运行1.2 beta 1。

还有其他想法可能导致了这个问题吗?这是我的旧回溯:

Traceback (most recent call last):
File "manage.py", line 4, in
import settings # Assumed to be in the same directory.
File "C:\dev\xxxxx\settings.py", line 53
('es', ugettext(u'Espa±ol') ),
SyntaxError: (unicode error) 'utf8' codec can't decode byte 0xf1 in position 0: unexpected end of data


1
经过研究,我只需要做两个更改:将gabi的“编码”标头(已经有了元标记)和@dominique-guardiola的强制Unicode解释都放入settings.py中。感谢大家的帮助和支持! - Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接