覆盖Model类的适当方法是什么 Django 1.4中的 getattr ?
我有一个模型结构,如:
class Main(models.Model):
[blah]
class Detail(models.Model):
main = models.ForeignKey(Main)
name = models.CharField(max_length=255)
value= models.CharField(max_length=255)
我覆盖了我的Main。 getattr _所以我可以引用Detail 记录好像它们是正常的主要属性。例如一个简单的元 模型模式如
>>> m = Main.objects.create()
>>> Detail.objects.create(main=m, name='name', value='value')
>>> print m.name
'value'
为此,我的1.4之前 getattr 看起来像是:
def __getattr__(self, attrname):
qs = self.details.filter(name=attrname)
c = len(qs)
if c == 0:
raise AttributeError
elif c == 1:
return qs[0].value
else:
return [d.value for d in qs]
这完美无缺,直到我升级到1.4。现在我得到了所有类型 “属性X不存在”错误。我试过像这样的东西 以下,但没有运气。它似乎特别与之相冲突 Django为ForeignKey引用生成的“_ * _ cache”属性。
def __getattr__(self, attrname):
try:
return super(Main, self).__getattr__(attrname)
except AttributeError:
pass
qs = self.details.filter(name=attrname)
c = len(qs)
if c == 0:
raise AttributeError
elif c == 1:
return qs[0].value
else:
return [d.value for d in qs]
我该如何解决这个问题?
答案 0 :(得分:1)
通过挖掘新的模型代码,似乎后端已经发生了很大的变化,因此Model类不再需要__getattr__
来覆盖。相反,我需要调用基础模型继承的object.__getattribute__
。但是,Django将缓存的数据存储在需要正确处理的特殊属性中。
我的新__getattr__
现在看起来像是:
def __getattr__(self, attrname):
try:
return super(Main, self).__getattribute__(attrname)
except AttributeError:
if attrname.startswith('_prefetched'):
raise
qs = self.details.filter(name=attrname)
c = len(qs)
if c == 0:
raise AttributeError
elif c == 1:
return qs[0].value
else:
return [d.value for d in qs]
答案 1 :(得分:1)
我没有尝试过,但__getattribute__()
可能会有效:
class Main(models.Model):
def __getattribute__(self, attrname):
try:
return super(Main, self).__getattribute__(attrname)
except AttributeError:
try:
return self.__getattr__(attrname)
except AttributeError:
# do your database accessing
但正如克里斯普拉特所说,这不是有点效率。您可能需要考虑缓存属性。