Как кэшировать метод модели в django?

У меня есть эта модель:

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]

Я заметил, что last_post создает очень затратный и часто выполняемый запрос. Поэтому я хочу кэшировать его на 5 минут.

Я знаю, как кэшировать набор запросов в представлениях, но last_post обходит представления и вызывается непосредственно в шаблоне. Так что оцените ваши подсказки о том, как его кэшировать.


person Jand    schedule 09.12.2015    source источник
comment
Возможно, cached_property это то, что вам нужно. См.: pydanny.com/cached-property.html.   -  person Alex Yu    schedule 10.12.2015
comment
Звучит отлично. Можете ли вы уточнить это как полный ответ, пожалуйста?   -  person Jand    schedule 10.12.2015
comment
@cached_property будет кэшировать результат для всего запроса, а не на 5 минут. Это, возможно, работает для вас.   -  person Lorenzo Peña    schedule 10.12.2015
comment
Обратите внимание, что в Django теперь доступен декоратор cached_property: docs.djangoproject.com/en/1.9/ref/utils/   -  person Thomas Druez    schedule 10.12.2015


Ответы (2)


Я предполагаю, что вы можете использовать cached_property_with_ttl из 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]

Надеюсь, это сработает для вас.

person Alex Yu    schedule 09.12.2015
comment
Большой! Единственная проблема в том, что я использую 1.8. который не имеет cached_property_with_ttl. Есть ли обходной путь для этого? - person Jand; 10.12.2015
comment
Это не реализация джанго. Это отдельный пакет. - person Alex Yu; 10.12.2015
comment
Ну, я получаю эту ошибку from cached_property import cached_property_with_ttl ImportError: No module named cached_property. Итак, как мне установить/импортировать его в 1.8? - person Jand; 10.12.2015
comment
На Windows и Ubuntu проблем нет. - person Alex Yu; 10.12.2015

EDIT: @Yassine Belmamoun указал, что это не сработает, потому что экземпляр умирает вместе с запросом.

Исходный ответ:

Как сказал @Thomas Druez, в Django теперь есть встроенный свойство_кэширования:

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]

Однако я не знаю, можно ли установить срок действия 5 минут. На той же странице написано, что кешированный результат будет сохраняться до тех пор, пока существует экземпляр.

person pianoJames    schedule 08.11.2019
comment
Декоратор cached_property будет существовать до тех пор, пока существует экземпляр. Это означает, что результат будет вычисляться для каждого нового запроса. Это не сработает. - person Yassine Belmamoun; 16.07.2020