[Fixed]-How do I memoize expensive calculations on Django model objects?


You may be interested in a built-in django decorator django.utils.functional.memoize.

Django uses this to cache expensive operation like url resolving.



Generally, I use a pattern like this:

def get_expensive_operation(self):
    if not hasattr(self, '_expensive_operation'):
        self._expensive_operation = self.expensive_operation()
    return self._expensive_operation

Then you use the get_expensive_operation method to access the data.

However, in your particular case, I think you are approaching this in slightly the wrong way. You need to do the deserialization when the model is first loaded from the database, and serialize on save only. Then you can simply access the attributes as a standard Python dictionary each time. You can do this by defining a custom JSONField type, subclassing models.TextField, which overrides to_python and get_db_prep_save.

In fact someone’s already done it: see here.


For class methods, you should use django.utils.functional.cached_property.

Since the first argument on a class method is self, memoize will maintain a reference to the object and the results of the function even after you’ve thrown it away. This can cause memory leaks by preventing the garbage collector from cleaning up the stale object. cached_property turns Daniel’s suggestion into a decorator.


Leave a comment