今天我通过Django管理员收到了无法编码的数据。不知何故,数据的编码不是unicode。这怎么可能?
我的name
模型中有一个Client
属性,它返回unicode中的数据:
@property
def name(self):
return u'{0} {1}'.format(self.firstname, self.lastname).strip()
但这不起作用:
>>> client
<Client: [Bad Unicode data]>
>>> client.lastname
'Dani\xc3\xabl'
>>> client.lastname.__class__
<type 'str'>
>>> u"{0} {1}".format(client.firstname, client.lastname)
Traceback (most recent call last):
File "<console>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
足够斯坦,将第一个/最后一个名称编码为常规字符串确实有效:
>>> "{0} {1}".format(client.firstname, client.lastname)
'Test Dani\xc3\xabl'
>>> "{0} {1}".format(client.firstname, client.lastname).decode('utf-8')
u'Test Dani\xebl'
这里发生了什么?以及这些输入是如何通过管理员进入我的模型的?
系统堆栈(它是外部服务器):
这是相关的型号代码:
class Client(models.Model):
firstname = models.CharField(_("Firstname"), max_length=255)
lastname = models.CharField(_("Lastname"), max_length=255)
email = models.EmailField(_("Email"), unique=True, max_length=255)
class Meta:
db_table = u'clients'
ordering = ('firstname', 'lastname', 'email')
def __unicode__(self):
return u'{0} <{1}>'.format(self.name, self.email)
@property
def name(self):
return u'{0} {1}'.format(self.firstname, self.lastname).strip()
答案 0 :(得分:3)
这可能是由于您对MySQL数据库使用的排序规则。
实际上,Django的行为是在从数据库中检索数据时始终返回unicode
字符串 - 这可以与您的代码一起使用,因为它没有任何问题。
但是,正如您在the django documentation on database settings中所看到的,使用MySQLdb版本1.2.2和utf8_bin
整理的MySQL数据库的部分整理设置将导致您不能获取unicode字符串,而是使用字节串,从数据库中检索字段。
您可能想要调查此问题(即检查您的MySQL排序规则设置),但很可能您的问题来自那里。
如果是这种情况,您将不得不手动解码从MySQL获得的任何输入。或者,您可以更改数据库的排序规则设置。
您可以使用SHOW TABLE STATUS FROM %YOURDB%
来获取数据库中表格的排序规则。
默认情况下,对于UTF-8数据库,MySQL将使用utf8_general_ci_swedish排序规则。这导致所有字符串相等性比较以不区分大小写的方式完成。也就是说,“Fred”和“freD”在数据库级别被认为是相同的。如果对字段有唯一约束,则尝试将“aa”和“AA”同时插入同一列是非法的,因为它们与默认排序规则相比较(因此,非唯一)。
在许多情况下,此默认值不会出现问题。但是,如果您确实需要对特定列或表进行区分大小写的比较,则应更改列或表以使用utf8_bin排序规则。在这种情况下要注意的主要事项是,如果您使用MySQLdb 1.2.2,Django中的数据库后端将为从数据库接收的任何字符字段返回字节串(而不是unicode字符串)。这是Django总是返回unicode字符串的常规做法的一个很大的变化。