在Django中,为什么我会遇到utf-8编码字符串的问题?

时间:2012-03-11 12:57:56

标签: python django encoding

我是德国开发人员为德国人编写Web应用程序,这意味着我无论如何都不能依赖纯ASCII编码。至少必须支持像ä,ö,ü,ß这样的字符。

幸运的是,Django默认将ByteStrings视为utf-8编码(如in the docs所述)。所以它应该工作,如果我将# -*- coding: utf-8 -*-行添加到每个.py文件的开头并设置编辑器编码,不应该吗?好吧,它大部分时间都在......

但是在网址方面我似乎错过了一些东西。或者也许这不会对URL做任何事情,但直到现在我还没有注意到任何其他编码错误行为。我记得有两种情况作为例子:

网址格式url(r'^([a-z0-9äöüß_\-]+)/$', views.view_page)无法识别包含ä,ö,ü,ß的网址。那些字符被简单地忽略了。

以下视图函数代码抛出异常:

def do_redirect(request, id):
    return redirect('/page/{0}'.format(id))

从URL中捕获id参数,如第一个示例中的那个。如果我修复了URL模式(通过将其指定为unicode字符串)而不是访问/ä/,我会得到异常

UnicodeEncodeError at /ä/
'ascii' codec can't encode character u'\xe4' in position 0: ordinal not in range(128)

但是,请为视图函数尝试以下代码:

def do_redirect(request, id):
    return redirect('/page/' + id)
一切都很好。这让我相信实际问题不在于Django,而是源自Python,将ByteStrings视为ASCII。我对编码没那么多,但第二个例子中的问题显然是String对象的format()方法。所以,在第一个例子中,由于Python处理正则表达式的方式,它可能会失败(虽然我不知道Django是否使用了re模块或其他东西)。

到目前为止,我的解决方法只是在发生此类错误时为字符串添加u前缀。这是一个糟糕的解决方案,因为我可能很容易忽略一些东西我尝试将每个Python字符串标记为unicode,但这会导致其他异常并且非常难看。

有没有人确切地知道,问题是什么以及如何以愉快的方式解决它(即当代码变大时不会让你的头爆炸的方式)?

提前致谢!

编辑:对于我的正则表达式,我发现了为什么需要u。将字符串指定为原始字符串(r)使其被解释为ASCII。离开r会使正则表达式在没有u的情况下正常工作,但会引入一些令人头疼的反斜杠。

2 个答案:

答案 0 :(得分:5)

使用u前缀字符串是解决方法。

如果这对您来说是一个问题,那么它看起来像是一个更普遍问题的症状:您的代码中有很多magic constants。这很糟糕(你已经明白了原因)。尽量避免使用它们,例如,您可以使用named url pattern or view name进行重定向,而不是重新键入URL的一部分。

如果无法避免它们,请将它们转换为命名常量,并将其分配放在一个位置。然后,你会发现所有这些都是正确的前缀,很难忽视它。

答案 1 :(得分:1)

在django 1.4中,其中一项新功能是对url internationalization的更好支持,包括支持翻译网址。

这对帮助你有很大的帮助,但这并不意味着你应该忽略其他建议,因为这一般适用于Python,并适用于所有,而不仅仅是django。< / p>