感到困惑的是python __str__方法和unicode行为

时间:2017-08-03 16:24:46

标签: python django unicode

这是Python 2.7。不要评判我。 :)

我有一个Django应用程序,其中类文件用于一些审计。由于历史原因,我在这个类中有一个__str__方法,我试图返回一些有用的东西。

   def __str__(self):
      return "%s %s" % (self.guid, self.setside_username)

现在,由于审计日志间接调用__str__,因此setside_username中的非ascii字符失败了

log.info("change to %s", obj)

我尝试将__str__重命名为__unicode__,但它仍然在同一位置失败。所以我尝试通过ascii编码来清理字符串并让编码器替换它不理解的任何东西。

def __str__(self):
   return "%s %s" % (self.guid, self.setside_username.encode('ascii', 'replace')

但该行因UnicodeDecodeError而失败,这令我感到困惑,因为我认为该调用会告诉编码器替换它不理解的任何内容。

为了证明我不理解encode()和decode()之间的区别,我/编码/解码,突然错误消失了。

我还没有找到原因。我认为解码创建了unicode对象并编码了创建的字节字符串,那么为什么在unicode对象上解码会有帮助?

更糟糕的是,我的小测试脚本只是使用print语句打印对象现在失败了!

    username = self.setside_username.decode('ascii', 'replace')
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 1: ordinal not in range(128)

所以我修复了一个用例但又打破了另一个用例。

我需要明白这一点,要知道我实际上已经解决了这个问题,而不仅仅是在回溯消失之前玩w鼹鼠。

帮助表示赞赏。

更新:转移到返回unicode的__unicode__方法。

仍然看到这一点。

Traceback (most recent call last):
  File "/usr/lib64/python2.6/logging/__init__.py", line 784, in emit
    msg = self.format(record)
  File "/usr/lib64/python2.6/logging/__init__.py", line 662, in format
    return fmt.format(record)
  File "/usr/lib64/python2.6/logging/__init__.py", line 444, in format
    record.message = record.getMessage()
  File "/usr/lib64/python2.6/logging/__init__.py", line 314, in getMessage
    msg = msg % self.args
  File "/etc/e-smith/web/django/teleworker/clients/models.py", line 364, in __unicode__
    return u"%s %s" % (self.guid, self.setside_username)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)
[03/Aug/2017 12:59:03.907] ERROR [MainThread] [tug-eventd.tug-eventd:1727] Error handling cluster event: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)

1 个答案:

答案 0 :(得分:2)

您需要为模型提供实际返回Unicode的__unicode__方法

def __unicode__(self):
   return u"%s %s" % (self.guid, self.setside_username)

注意u前缀,我们使用了Unicode文字,但我们没有对用户名进行编码。

Django模型基类http://localhost:8998,它将获取__unicode__输出并将其编码为字节串。