How can I handle dynamic calculated attributes in a model in Django?
In Django I calculate the breadcrumb (a list of fathers) for an geographical object. Since it is not going to change very often, I am thinking of pre calculating it once the object is saved or initialized.
1.) What would be better? Which solution would have a better performance? To calculate it at ____init____ or to calculate it when the object is saved (the object takes about 500-2000 characters in the DB)?
2.) I tried to overwrite the ____init____ or save() methods but I don't know how to use attributes of the just saved obje开发者_如何学Goct. Accessing *args, **kwargs did not work. How can I access them? Do I have to save, access the father and then save again?
3.) If I decide to save the breadcrumb. Whats the best way to do it? I used http://www.djangosnippets.org/snippets/1694/ and have crumb = PickledObjectField().
The model:
class GeoObject(models.Model):
name = models.CharField('Name',max_length=30)
father = models.ForeignKey('self', related_name = 'geo_objects')
crumb = PickledObjectField()
# more attributes...
Thats the method to calculate the attribute crumb()
def _breadcrumb(self):
breadcrumb = [ ]
x = self
while True:
x = x.father
try:
if hasattr(x, 'country'):
breadcrumb.append(x.country)
elif hasattr(x, 'region'):
breadcrumb.append(x.region)
elif hasattr(x, 'city'):
breadcrumb.append(x.city)
else:
break
except:
break
breadcrumb.reverse()
return breadcrumb
Thats my save-Method:
def save(self,*args, **kwargs):
# how can I access the father ob the object?
father = self.father # does obviously not work
father = kwargs['father'] # does not work either
# the breadcrumb gets calculated here
self.crumb = self._breadcrumb(father)
super(GeoObject, self).save(*args,**kwargs)
Please help me out. I am working on this for days now. Thank you.
By calling both the _breadcrumb method with x.father and assigning x = x.father in the beginning of the while loop you jump over one father. Try exchanging
self.crumb = self._breadcrumb(father)
with
self.crumb = self._breadcrumb(self)
By defining _breadcrumb within the model class you can clean it up like this:
class GeoObject(models.Model):
name = models.CharField('Name',max_length=30)
father = models.ForeignKey('self', related_name = 'geo_objects')
crumb = PickledObjectField()
# more attributes...
def _breadcrumb(self):
...
return breadcrumb
def save(self,*args, **kwargs):
self.crumb = self._breadcrumb()
super(GeoObject, self).save(*args,**kwargs)
For more complex hierachies I recomend django-treebeard
精彩评论