在Django中,为什么我会遇到utf-8编码字符串的问题?
我是德国开发人员,为德国人编写Web应用程序,这意味着我无法通过任何方式依赖纯ASCII编码。至少需要支持ä,ö,ü,ß等字符。在Django中,为什么我会遇到utf-8编码字符串的问题?
幸运的是,Django的对待字节串为UTF-8编码的默认(如所描述的in the docs)。所以它应该可以工作,如果我将# -*- coding: utf-8 -*-
行添加到每个.py文件的开头并设置编辑器编码,不是吗?嗯,它大部分时间都是这样的......
但是,在网址方面,我似乎错过了一些东西。或者,也许这并没有对URL做任何事情,但直到现在我没有注意到任何其他编码不当行为。我记得有两种情况作为示例:
URL模式url(r'^([a-z0-9äöüß_\-]+)/$', views.view_page)
根本不能识别包含ä,ö,ü,ß的URL。这些字符简单地被忽略。
的视图函数的下面的代码抛出异常:
def do_redirect(request, id):
return redirect('/page/{0}'.format(id))
其中ID参数从像在第一示例中的URL捕获。如果我定的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
的情况下工作,但引入了一些反斜线的头痛。
使用u
为字符串添加前缀是解决方案。
如果这是你的问题,那么它看起来像一个更一般的问题的症状:您在代码中有很多magic constants。这是不好的(你已经看到了为什么)。尽量避免它们,例如,您可以使用进行重定向,而不是重新输入URL的部分。
如果无法避开他们,把他们变成命名常量,并将其分配在同一个地方。然后,你会发现它们都是正确的前缀,很难忽略它。
感谢您的提示。命名的网址模式是我所需要的。 – j0ker 2012-03-11 17:11:39
在django 1.4中,其中一个新功能是更好地支持url internationalization,包括支持翻译URL。
这将帮助你走出很长的路,但这并不意味着你应该忽略其他建议,因为它适用于所有Python,并且适用于所有内容,而不仅仅是django。
“这是一个糟糕的解决方案,因为我可能很容易忽略某些东西。”嗯,不,这就是*解决方案。 – 2012-03-11 13:02:20
我的问题是,我不知道哪些字符串是危险的,因为我不知道他们为什么失败。它确实有效,但我永远不能说我是否阻止了所有潜在的编码错误。所以,这是一个糟糕的解决方案_for me_;) – j0ker 2012-03-11 13:10:28
这就是python现在的工作方式。 Python3将有望解决这些问题。 – 2012-03-11 13:24:45