03.11.2019       Выпуск 306 (28.10.2019 - 03.11.2019)       Статьи

Кэширование свойств объектов моделей с помощью model_cached_property

model_cached_property - это декоратор для кэширования свойств объектов моделей данных в Django. Данный декоратор позволяет кэшировать свойства объектов моделей в зависимости от входных параметров на заданный период времени. В статье описываются варианты применения, а также ограничения декоратора.

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

Для ускорения работы сайта помимо оптимизации запросов к базе данных можно использовать и кэширование.

Django позволяет выполнять кэширование:

  • отдельных view , как Class Based View , так и обычных функций view
  • целых шаблонов или их частей
  • целых QuerySet
  • а также свойств объектов моделей с помощью cached_property

Меня интересовала возможность кэширования отдельных свойств объектов моделей для тяжёлый вычислений или тяжёлых запросов к базе данных.
Таким фукционалом обладает декоратор cached_property , но недостаток для меня заключался в том, что кэширование происходило лишь на период жизни объекта.
Тогда как мне требуется кэширование на больший пероид времени, чем существование объекта при запросе страницы. А также мне требовалось кэширование свойств в зависимости от входных аргументов. Данный декоратор на сайте кэширует количество лайков и дислайков, а также информацию о том, лайкнул ли текущий пользователь тот или иной объект контента.

Таким образом был написан декоратор model_cached_property

model_cached_property

Данный декоратор использует в качестве бэкенда кеширования redis , поскольку для инвалидации кэша может потребоваться удаление группы ключей, которые относятся к данному свойству. Поскольку свойство может кэшироваться для разных пользователей по разному.

Установка EVILEG-CORE

Устанавливаем EVILEG-CORE.

pip install evileg-core

Также evileg_core подтянет все необходимые для данного пакета зависимости. В том числе библиотеку django-redis , которая используется для работы с redis .

Если вы ещё не используете у себя redis , то потребуется его установить.

sudo apt install redis-server

settings.py

Добавляем evileg_core в установленные приложения

INSTALLED_APPS = [
    ...
    'evileg_core',
]

Настраиваем бэкенд кэширования

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

Использование model_cached_property

Обычное кэширование

from evileg_core.cache.decorators import model_cached_property

class Article(models.Model):

    @model_cached_property
    def comments_count(self):
        return self.comments.count()

Данный декоратор будет кэшировать количество комментариев к статье на 60 секунд. При следующем запросе страницы статьи запрос будет выполнен сначала к кэшу для конкретного объекта статьи, и только если длительность кэша истекла, то запрос будет снова выполнен к базе данных.

Установка длительности кэширования

Если же вы хотите задать определённое время кэширования, то можете использовать аргумент timeout у декоратора.

class Article(models.Model):

    @model_cached_property(timeout=3000)
    def comments_count(self):
        return self.comments.count()

Глобальная установка длительности кэширования

Также можно задать глобальное время кэширования для всех декораторов в файле settings.py в секундах

MODEL_CACHED_PROPERTY_TIMEOUT = 300000

Использование свойств с аргументами

А теперь самое интересное. Кэширование свойств с аргументами, благодаря которому можно кэшировать результат с помощью информации о входных аргуметах свойства модели данных.

Это является как преимуществом данного декоратора, так и его недостатком. Дело в том, чтобы кэширование было корректным, необходимо, чтобы входные аргументы были уникальными. Например, если входные аргументы являются временными неуникальными объектами, как AnonymousUser , то кэширование не будет работать.

Тем не менее, декоратор может использоваться для кэширования в зависимости от пользователя. Это может выглядеть следующим образом.

class Article(models.Model):

    @model_cached_property
    def __user_in_bookmarks(self, user):
        return self.bookmarks.filter(user=user).exists()

    def user_in_bookmarks(self, user):
        return self.__user_in_bookmarks(user) if user.is_authenticated else False

Обратите внимание, что здесь имеется проверка на user.is_authenticated , поскольку кэширование неаутентифицированного пользователя не будет работать корректно, однако будет работать корректно для аутентифицированного пользователя, поскольку аутентифицированный пользователь является уникальным объектом.

Инвалидация кэша

В том случае, если кэш стал неактуальным раньше времени истечения его жизни, то вы можете воспользоваться функцией invalidate_model_cached_property

from evileg_core.cache.utils import invalidate_model_cached_property

class Article(models.Model):

    def invalidate_cache(self):
        invalidate_model_cached_property(self, self.comments_count)

Для корректной инвалидации кэша необходимо передать объект, кэш которого необходимо очистить, а также метод этого объекта.

Это может выглядеть также и таким образом

article = get_object_or_404(Article, pk=12)
invalidate_model_cached_property(article, article.comments_count)

Заключение

Таким образом model_cached_property может использоваться для

  • кэширования свойств объектов моделей на длительный срок, больше чем время жизни объекта при запросе страницы
  • кэширования свойств объектов моделей в зависимости от входных аргументов

При этом имеются ограничения

  • данный декоратор может использоваться только в моделях, то есть классов, наследованных от models.Model
  • кэширование свойств моделей в зависимости от аргументов должно выполняться только для уникальных входных аргументов, иначе кэширование не будет корректным





Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus