我刚创建了以下模型:
class Categoria(models.Model):
nombre=models.CharField(max_length=30)
padre=models.ForeignKey('self', blank=True, null=True)
def __unicode__(self):
return self.nombre
然后注册到管理界面和syncdb'd
如果我只添加纯ASCII字符,一切都好。但如果我添加名为“á”的“类别”(说些什么),我会得到:
Environment:
Request Method: GET
Request URL: http://192.168.2.103:8000/administracion/locales/categoria/
Django Version: 1.1.1
Python Version: 2.6.4
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',
'cruzandoelsuquiaDJ.locales']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware')
Template error:
In template /usr/lib/pymodules/python2.6/django/contrib/admin/templates/admin/change_list.html, error at line 78
Caught an exception while rendering: ('ascii', '\xc3\xa1', 0, 1, 'ordinal not in range(128)')
68 : {% endif %}
69 : {% endblock %}
70 :
71 : <form action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}>
72 : {% if cl.formset %}
73 : {{ cl.formset.management_form }}
74 : {% endif %}
75 :
76 : {% block result_list %}
77 : {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %}
78 : {% result_list cl %}
79 : {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %}
80 : {% endblock %}
81 : {% block pagination %}{% pagination cl %}{% endblock %}
82 : </form>
83 : </div>
84 : </div>
85 : {% endblock %}
86 :
Traceback:
File "/usr/lib/pymodules/python2.6/django/core/handlers/base.py" in get_response
92. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/pymodules/python2.6/django/contrib/admin/options.py" in wrapper
226. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/lib/pymodules/python2.6/django/views/decorators/cache.py" in _wrapped_view_func
44. response = view_func(request, *args, **kwargs)
File "/usr/lib/pymodules/python2.6/django/contrib/admin/sites.py" in inner
186. return view(request, *args, **kwargs)
File "/usr/lib/pymodules/python2.6/django/contrib/admin/options.py" in changelist_view
986. ], context, context_instance=context_instance)
File "/usr/lib/pymodules/python2.6/django/shortcuts/__init__.py" in render_to_response
20. return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "/usr/lib/pymodules/python2.6/django/template/loader.py" in render_to_string
108. return t.render(context_instance)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
178. return self.nodelist.render(context)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
779. bits.append(self.render_node(node, context))
File "/usr/lib/pymodules/python2.6/django/template/debug.py" in render_node
71. result = node.render(context)
File "/usr/lib/pymodules/python2.6/django/template/loader_tags.py" in render
97. return compiled_parent.render(context)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
178. return self.nodelist.render(context)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
779. bits.append(self.render_node(node, context))
File "/usr/lib/pymodules/python2.6/django/template/debug.py" in render_node
71. result = node.render(context)
File "/usr/lib/pymodules/python2.6/django/template/loader_tags.py" in render
97. return compiled_parent.render(context)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
178. return self.nodelist.render(context)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
779. bits.append(self.render_node(node, context))
File "/usr/lib/pymodules/python2.6/django/template/debug.py" in render_node
71. result = node.render(context)
File "/usr/lib/pymodules/python2.6/django/template/loader_tags.py" in render
24. result = self.nodelist.render(context)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
779. bits.append(self.render_node(node, context))
File "/usr/lib/pymodules/python2.6/django/template/debug.py" in render_node
71. result = node.render(context)
File "/usr/lib/pymodules/python2.6/django/template/loader_tags.py" in render
24. result = self.nodelist.render(context)
File "/usr/lib/pymodules/python2.6/django/template/__init__.py" in render
779. bits.append(self.render_node(node, context))
File "/usr/lib/pymodules/python2.6/django/template/debug.py" in render_node
81. raise wrapped
Exception Type: TemplateSyntaxError at /administracion/locales/categoria/
Exception Value: Caught an exception while rendering: ('ascii', '\xc3\xa1', 0, 1, 'ordinal not in range(128)')
我的django版本是1.1,我的数据库是5.1.37-1ubuntu5,带有utf8字符集,表格使用了utf8_bin校对。
这个问题看起来太基本了,而且我是一个django新手,所以如果我错过了一些非常简单的话,我会提前感到抱歉:)
答案 0 :(得分:17)
Django通常具有非常好的Unicode支持(有关详细信息,请参阅Django 1.1 "Unicode data" documentation)。在我的代码中,我发现,如果我遇到简单的Unicode功能问题,问题通常是我不能很好地理解Django的细节,而不是Django的Unicode支持有错误。
“Unicode数据”页面告诉我们“所有Django的数据库后端......自动将从数据库中检索到的字符串转换为Python Unicode字符串。您甚至不需要告诉Django您的数据库使用什么编码:即透明地处理。“所以你的简单return self.nombre
应该返回一个Python Unicode字符串。
但是,Django 1.1 "Databases" page有一个关于MySQL后端如何处理utf8_bin
排序规则的重要说明:
...如果你真的想要区分大小写的话 比较特定列或 表,你会改变列或 表使用utf8_bin排序规则。 在这方面要注意的主要事项 如果你使用的是MySQLdb 1.2.2,Django中的数据库后端将返回bytestrings(而不是 unicode字符串)任何字符 它返回的字段是从 数据库。这是一个很大的变化 来自Django的正常做法 总是返回unicode字符串。它 由开发人员负责处理 你将收到的事实 如果你配置你的字节串 要使用utf8_bin排序规则的表格。 Django本身应该顺利运作 有这样的列,但如果你的代码 必须准备打电话 django.utils.encoding.smart_unicode() 有时,如果它真的想工作 数据一致......
因此,在您的原始示例中,“nombre”列使用了utf8_bin排序规则。这意味着self.nombre
正在返回一个Python字节字符串。当您将其放在需要Python Unicode字符串的表达式中时,Python会执行其默认转换。这相当于self.nombre.decode('ascii')
。当然,.decode('ascii')
在遇到0x7F以上的任何字节时都会失败,例如编码“á”的UTF-8字节。
您发现了解决此问题的两种方法。第一种是将self.nombre
返回的Python字节字符串显式转换为Python Unicode字符串。我敢打赌,以下更简单的代码会起作用:
return self.nombre.decode('utf8')
第二种方法是更改列“nombre”的MySQL排序规则,这会导致Django的MySQL后端返回Python Unicode字符串而不是异常字节字符串。然后你的原始表达式给出了一个Python Unicode字符串:
return self.nombre
希望这有帮助。
答案 1 :(得分:7)
这个问题可以通过稍微更改django的代码来解决。 在django / utils / encoding.py
中添加以下代码import sys
reload(sys)
sys.setdefaultencoding('utf-8')
答案 2 :(得分:4)
我在生产中遇到过这个问题,从不在开发服务器上
然后我意识到新表是使用utf8_bin
整理而不是utf8_general_ci
创建的。
要查看哪些表需要转换,请键入
SHOW TABLE STATUS;
然后通过键入
转换utf8_bin
归类的那些
ALTER TABLE app_table CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
最后,更改默认排序规则,以便不再发生这种情况:
ALTER DATABASE my_database character set utf8 collate utf8_general_ci;
答案 3 :(得分:2)
好的......
return u"%s"%(self.nombre.decode('utf8'),)
诀窍。
但是也发现将utf8_bin改为utf8_general_ci可以解决问题,即self.nombre按预期工作。
答案 4 :(得分:1)
我通过简单地为模型创建管理模型并在&#34; list_display&#34;中包含所有变量来解决问题。
答案 5 :(得分:0)
我有类似的问题,最近改变了一个MySQL表,在staging中使用collation utf8_bin而dev中没有问题(python2.7,两个环境中的Django1.4.2)。我发现在开发中我有MySQL-python 1.2.4c1并且在暂存中我有1.2.3。升级到MySQL-python 1.2.4为我解决了这个问题。