DjangoUnicodeDecodeError:[错误的Unicode数据]

时间:2014-10-05 21:05:35

标签: python django unicode python-unicode

模特:

class ItemType(models.Model):
  name = models.CharField(max_length=100)
  def __unicode__(self):
    logger.debug("1. Item Type %s created" % self.name)
    return self.name 

代码:

  (...)
    type = re.search(r"Type:(.*?)",text)
    itemtype = ItemType.objects.create(name = name.group(1), defaults={'name':name.group(1)})
    logger.debug("2. Item Type %s created" % name.group(1))
    logger.debug("4. Item Type %s created" % itemtype.name)
    logger.debug("3. Item Type %s created" % itemtype)

结果出乎意料(对我来说当然):

第一个logger.debug按预期打印Item Type ąęńłśóć created,但第二个引发错误:

DjangoUnicodeDecodeError: 'ascii' codec can't decode byte  in position : 
ordinal not in range(128). 
You passed in <ItemType: [Bad Unicode data]> (<class 'aaa.models.ItemType'>)

为什么会出现错误,我该如何解决?

(文本是​​使用utf-8编码的html响应)

更新

我将调试添加到模型中,调试结果是:

2014-10-06 09:38:53,342 DEBUG views 2. Item Type ąęćńółśż created
2014-10-06 09:38:53,342 DEBUG views 4. Item Type ąęćńółśż created
2014-10-06 09:38:53,344 DEBUG models 1. Item Type ąęćńółśż created
2014-10-06 09:38:53,358 DEBUG models 1. Item Type ąęćńółśż created

那么为什么调试3.无法打印呢?

更新2 问题出在这里:

  itemtype = ItemType.objects.create(name = name.group(1), defaults={'name':name.group(1)})

如果我把它改成

  itemtype = ItemType.objects.create(name = name.group(1), defaults={'name':u'ĄĆĘŃŁÓŚ'})

一切都很好。

那么如何将其转换为unicode? unicode(name.group(1))不起作用。

1 个答案:

答案 0 :(得分:3)

经过两天与自己的阴影相比,我找到了解决方案。对于这种情况,这不是一种解决方法,但思维的复杂变化,我必须重构整个代码。

  1. 我的假设是每个字符串都是UNICODE。如果不是 - 修复它。

  2. 不要使用“%s”或“某事”总是使用你的“%s”和你“cośtam”

  3. 在每个有models.CharField()或其他“文本”导向字段的模型中,我都覆盖了save()方法:
  4. 例如

    class ItemType(models.Model):
      name = models.CharField(max_length=100)
    
      def save(self, *args, **kwargs):
        if isinstance(self.name, str):
          self.name=self.name.decode("utf-8")
        super(ItemType, self).save(*args, **kwargs)
    

    解释 - 如果某个名称填充了str而不是unicode - 将其更改为unicode。

    我是如何找到这个的:

    我想知道models.CharField中的文本是什么类型,并且发现,如果用unicode填充它 - 它是unicode,如果你填充 - str - 它是str。所以,如果你曾经用unicode“手”填充它,而在其他地方正则表达式用str填充它 - 结果是意外的。

    unicode和str的最大问题是使用diactrics同时没有问题:

    >>> text_str = "żółć"
    >>> text_unicode = u"żółć"
    >>> print text_str
    żółć
    >>> print text_uni
    żółć
    

    所以你看不出差异。

    但是如果你使用其他命令:

    >>> text_str
    '\xc5\xbc\xc3\xb3\xc5\x82\xc4\x87'
    >>> text_uni
    u'\u017c\xf3\u0142\u0107'
    

    差异很大。

    如果有一些设置可以改变print(和similiars)的行为:

    >>> print text_str
    '\xc5\xbc\xc3\xb3\xc5\x82\xc4\x87'
    >>> print text_uni
    żółć
    

    一切都会更容易调试 - 如果你能看到diactrics它没关系 - 如果没有 - 它很糟糕。

    使用解码('utf-8')引导我找到解决方案:

    >>> text_str
    '\xc5\xbc\xc3\xb3\xc5\x82\xc4\x87'
    >>> text_str.decode('utf-8')
    u'\u017c\xf3\u0142\u0107'
    >>> text_uni
    u'\u017c\xf3\u0142\u0107'
    

    VOILA!