Monday, June 4, 2012

Appropriate way to override Model __getattr__ in 1.4

What's the appropriate way of overriding the a Model class's
__getattr__ in Django 1.4?

I have a model structure like:

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)

I had overridden my Main._getattr__ so I could reference Detail
records as though they were normal Main attributes. e.g. a simple meta-
model pattern like

>>> m = Main.objects.create()
>>> Detail.objects.create(main=m, name='name', value='value')
>>> print m.name
'value'

To do this, my pre-1.4 __getattr__ looked like:

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]

This worked perfectly until I upgraded to 1.4. Now I get all types
"attribute X does not exist" errors. I tried something like the
following, but had no luck. It seems to especially conflict with the
"_*_cache" attributes Django generates for ForeignKey references.

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]

How do I resolve this?

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment