Python 覆盖1.4中模型的适当方法

Python 覆盖1.4中模型的适当方法,python,django,django-models,Python,Django,Django Models,重写模型类的 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,因此可以引用详

重写模型类的 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,因此可以引用详细信息 记录,就好像它们是正常的主属性一样。e、 g.一个简单的元数据- 模型样

>>> 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引用生成的“*\u缓存”属性

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]

我如何解决这个问题

通过挖掘新的模型代码,似乎后端已经发生了实质性的更改,因此模型类不再有要覆盖的
\uuuuu getattr\uuuuu
。相反,我需要调用基本模型从中继承的
对象。但是,Django将缓存的数据存储在特殊属性中,需要正确处理这些属性

我的新
\uuu getattr\uuuu
现在看起来像:

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]
我还没试过这个,但可能有用:

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

但正如克里斯·普拉特所说,这一点效率都不高。你可能想考虑缓存你的属性。

这是一个停下来问问题的好时机:为什么H-E-Houth-Hook-Boo棒在这么做?它不仅看起来像一个肮脏的黑客,而且效率极低,每次访问实例上的属性时都会生成一个数据库查询。你甚至没有缓存任何东西。不可否认,我的情况不同寻常。简单地说,我的模型允许用户定义自己的自定义模型。缓存很容易添加,为了简单起见,我省略了它。
getattr(self,name)
将调用
self.\uu getattribute\uuuu(name)
,导致无限递归。这会导致
运行时错误:超过最大递归深度。