Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cache a model method in django?

I have this model:

class Article(models.Model):
    title = models.CharField(max_length=300, blank=False)
    body = models.TextField(max_length=10000, blank=False)
    created = models.DateTimeField(auto_now_add=True)


    def last_post(self):
        if self.post_set.count():
            return self.post_set.order_by("-created")[0]

I have noticed that the last_post creates a very costly and frequently run query. So I want to cache it for 5 minutes.

I know how to cache a queryset in views but last_post bypasses views and is directly called in template. So appreciate your hints on how to cache it.

like image 570
Jand Avatar asked Dec 09 '15 21:12

Jand


Video Answer


2 Answers

I suppose that you can use cached_property_with_ttl from https://pypi.python.org/pypi/cached-property/1.2.0

from cached_property import cached_property_with_ttl

class Article(models.Model):
    title = models.CharField(max_length=300, blank=False)
    body = models.TextField(max_length=10000, blank=False)
    created = models.DateTimeField(auto_now_add=True)

    @cached_property_with_ttl(ttl=5)
    def last_post(self):
        if self.post_set.count():
            return self.post_set.order_by("-created")[0]

Hope this will work for you.

like image 136
Alex Yu Avatar answered Sep 19 '22 11:09

Alex Yu


EDIT : @Yassine Belmamoun pointed out that this won't work because the instance dies with the request.

Original answer:

As @Thomas Druez said, Django now has a built-in cached_property:

from django.utils.functional import cached_property

class Article(models.Model):

    @cached_property
    def last_post(self):
        if self.post_set.count():
            return self.post_set.order_by("-created")[0]

However, I don't know if you can set a 5 min expiration. The same page says "The cached result will persist as long as the instance does."

like image 34
pianoJames Avatar answered Sep 21 '22 11:09

pianoJames