[Answered ]-Appropriate way to override Model __getattr__ in 1.4

1👍

Digging through the new model code, it seems the backend has been changed substantially, so that the Model class no longer has a __getattr__ to override. Instead, I need to call object.__getattribute__, which the base model inherits from. However, Django stores cached data in special attributes, which need to be properly handled.

My new __getattr__ now looks like:

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]
👤Cerin

1👍

I haven’t tried this, but __getattribute__() might work:

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

But as Chris Pratt said, this is not a bit efficient. You might want to consider caching your attributes.

Leave a comment