Reputation: 2727
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
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.
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
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