我正在尝试更改 Django 模型的行为以允许我直接从父项访问外键的属性,例如
cache.part_number
vs
cache.product.part_number
我试过如下覆盖 __getattr__
方法,但是当我尝试访问外键的属性时出现递归错误
class Product(models.Model):
part_number = models.CharField(max_length=10)
...
class Cache(models.Model):
product = models.ForeignKey(Product)
...
def __getattr__(self, name):
value = getattr(self.product, name, None)
if value:
return value
else:
raise AttributeError
我做错了什么?
最佳答案
考虑您的 __getattr__
方法中的代码:
value = getattr(self.product, name, None)
尝试猜测调用 self.product
时会发生什么。我会给你一个线索:它涉及对 __getattr__
的调用。 documentation有详细信息:
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.
您是否想知道 self.product
如何解析为正确的 Product
实例,即使您没有在任何地方设置它?
Note that if the attribute is found through the normal mechanism,
__getattr__()
is not called.
Django 做了一些涉及拦截的魔法,您猜对了,__getattr__
。因此 self
自动以属性 product
结束。由于您正在覆盖 __getattr__
方法,Django 的魔力将停止工作并使用您的版本。由于 self.product
不是实例属性,__getattr__
会被再次调用,如此反复,导致无限循环。
你最好使用 property
实现这一目标。
class Cache(models.Model):
product = models.ForeignKey(Product)
...
def _get_part_number(self):
part_number = self.product.part_number
if not part_number:
raise AttributeError
return part_number
part_number = property(_get_part_number)
关于python - 使用 __getattr__ 更改 Django 模型的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3757951/