drj*_*eep 5 python django class
我正在尝试更改Django模型的行为,以允许我直接从父级访问外键的属性,例如
cache.part_number
vs
cache.product.part_number
Run Code Online (Sandbox Code Playgroud)
我尝试重写该__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
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
考虑__getattr__方法中的代码:
value = getattr(self.product, name, None)
Run Code Online (Sandbox Code Playgroud)
尝试猜测self.product调用时会发生什么.我会给你一个线索:它涉及到一个电话__getattr__.该文件有详细介绍:
当属性查找未在通常位置找到属性时调用(即,它不是实例属性,也不是在类树中找到自己).name是属性名称.此方法应返回(计算)属性值或引发AttributeError异常.
你有没有想过如何self.product解决正确的Product实例,即使你没有把它设置在任何地方?
请注意,如果通过常规机制找到属性,
__getattr__()则不会调用该属性.
Django做了一些涉及拦截的魔法,你猜对了__getattr__.从而self自动以一个属性结束product.由于你重写了这个__getattr__方法,Django的魔法停止工作,你的版本被使用了.因为self.product不是实例属性,__getattr__所以再次调用,再次调用,依此类推,导致无限循环.
你最好用a 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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3629 次 |
| 最近记录: |