这个让我困惑。考虑以下Django模型-代表动物园管理员和他们负责清洁的动物园笼子:
class Zookeeper(moodels.Model):
name = models.CharField(max_length=40)
class Cage(models.Model):
zookeeper = models.ForeignKey(Zookeeper)
现在假设我要将接收器连接到Cage
的post_init
信号:
@receiver(models.signals.post_init, sender=Cage)
def on_cage_init(instance, **kwargs):
print instance.zookeeper
正如预期的那样,这会引发异常,因为Cage
尚未分配给Zookeeper
。考虑对接收器主体进行以下修改:
print getattr(instance, 'zookeeper', 'No Zookeeper')
有人会希望这会打印“没有Zookeeper”,因为其中一个没有分配给实例。相反,会引发异常:
Traceback (most recent call last):
File "../zoo/models.py", line 185, in on_cage_init
print getattr(instance, 'zookeeper', 'No Zookeeper')
File "/usr/local/lib/python2.7/dist-packages/django/db/models/fields/related.py", line 324, in __get__
"%s has no %s." % (self.field.model.__name__, self.field.name))
DoesNotExist: Cage has no zookeeper.
为什么会有例外?如果属性不存在,getattr()
不应该返回提供的默认值吗?我可以证明该属性不存在于:
print hasattr(instance, 'zookeeper')
…打印False
。
很可能该类定义了
__getattribute__
。请参见以下示例:注意
getattr
实际上是如何在内部调用o.__getattribute__
,如果这引发了一个泛型异常,那么它将因该异常而失败。但是,如果正确地定义了提升
AttributeError
,那么getattr
将正确地捕获它。因此,这可以被认为是
DoesNotExist
异常定义中的一个错误,因为它没有正确地从AttributeError
继承。一个更完整的示例来演示以上所有内容:
当然,以上这些并不能帮助你解决这个错误。与其等待错误被解决,不如实现捕获该异常(或您可能期望的任何其他异常)的
getattr
。类似的事情可能会奏效:@metatoaster的解释非常好,基本上就是这样。请参阅
__get__
定义的魔法方法here。作为解决方案,我将应用"Easier to ask for forgiveness than permission"原则。尝试获取属性并捕获特定异常:
相关问题 更多 >
编程相关推荐