Python - caching properties to avoid future calculations

The following example is cached_attrused to get or set an attribute in a model instance when a resource with a high database cost is called ( related_spamin the example). In the example, I use cached_spamto save queries. I set print instructions when setting up and getting values ​​so that I can verify this. I tested it in the view, passing an instance Eggto the view and in the view using {{ egg.cached_spam }}, as well as other methods in the model Eggthat make callscached_spamyourself. When I finished and tested it, shell output on the Django development server showed that the attribute cache was skipped several times and also successfully received several times. This seems to be inconsistent. With the same data, when I made small changes (as soon as I changed the line of the print line) and updated (with all the same data), a different number of misses / successes occurred. How and why is this happening? Is this code incorrect or very problematic?

class Egg(models.Model):
    ... fields

    @property
    def related_spam(self):
        # Each time this property is called the database is queried (expected).
        return Spam.objects.filter(egg=self).all()  # Spam has foreign key to Egg.

    @property
    def cached_spam(self):
        # This should call self.related_spam the first time, and then return
        # cached results every time after that.
        return self.cached_attr('related_spam')

    def cached_attr(self, attr):
        """This method (normally attached via an abstract base class, but put
        directly on the model for this example) attempts to return a cached
        version of a requested attribute, and calls the actual attribute when
        the cached version isn't available."""
        try:
            value = getattr(self, '_p_cache_{0}'.format(attr))
            print('GETTING - {0}'.format(value))
        except AttributeError:
            value = getattr(self, attr)
            print('SETTING - {0}'.format(value))
            setattr(self, '_p_cache_{0}'.format(attr), value)
        return value
+5
source share
2 answers

Something is wrong with your code as much as possible. The problem probably does not exist, but in how you use this code.

, , . , - Egg , , . cached_attr , .

, RelatedObject ForeignKey to Egg:

my_first_egg = Egg.objects.get(pk=1)
my_related_object = RelatedObject.objects.get(egg__pk=1)
my_second_egg = my_related_object.egg

my_first_egg my_second_egg pk 1, :

>>> my_first_egg.pk == my_second_egg.pk
True
>>> my_first_egg is my_second_egg
False

, my_first_egg my_second_egg.

, , ( , ), .

+9

Http, , ; - . , .

Django . ; locmem://, , .

+1

All Articles