Jand
Jand

Reputation: 2727

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.

Upvotes: 14

Views: 11059

Answers (2)

pianoJames
pianoJames

Reputation: 484

EDIT : @Yassine Belmamoun pointed out that this won't work because the instance dies with the request. I'm keeping it so people have an example of what NOT to do.

Original answer (DO NOT USE):

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
    ## DON'T USE THIS; IT DOES NOT WORK
    ## KEEPING AS REFERENCE OF WHAT NOT TO DO
    def last_post(self):
        if self.post_set.count():
            return self.post_set.order_by("-created")[0]

Upvotes: 2

Alex Yu
Alex Yu

Reputation: 3537

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.

Upvotes: 9

Related Questions