Evgenii Legotckoi
Evgenii LegotckoiҚар. 3, 2019, 4:03 Т.Ж.

ЖАМАНДЫҚ ЯРЕК. Model_cached_property бар үлгі нысанының сипаттарын кэштеу

Сайтты жеделдету үшін дерекқор сұрауларын оңтайландырудан басқа, кэштеуді пайдалануға болады.

Django кэштеуге мүмкіндік береді:

  • жеке көрініс , Класқа негізделген көрініс және тұрақты көру функциялары
  • тұтас үлгілер немесе осы үлгілердің бөліктері
  • Сұраулар жинағы
  • сонымен қатар cached_property көмегімен үлгі нысандарының қасиеттері

Мені ауыр есептеулер немесе ауыр дерекқор сұраулары үшін үлгі нысандарының жеке қасиеттерін кэштеу мүмкіндігі қызықтырды.
cached_property декораторының осындай функционалдығы бар, бірақ мен үшін минус кэштеу объектінің қызмет ету мерзімі ішінде ғана орын алды.
Ал маған бет сұралған кезде объектінің бар болуынан ұзақ уақыт бойы кэштеу қажет. Сондай-ақ кіріс аргументтеріне байланысты қасиеттерді кэштеу керек болды. Бұл сайт безендірушісі ұнатулар мен ұнатпаулар санын, сондай-ақ ағымдағы пайдаланушыға белгілі бір мазмұн элементін ұнатқан-ұнамағаны туралы ақпаратты кэштейді.

model_cached_property декораторы осылай жазылған


үлгінің_кэштелген_сипаты

Бұл декоратор өзінің кэштеу механизмі ретінде redis пайдаланады, себебі кэшті жарамсыз деп тану үшін осы сипатқа жататын кілттер тобын жою қажет болуы мүмкін. Өйткені сипат әртүрлі пайдаланушылар үшін әртүрлі жолдармен кэштелуі мүмкін.

EVILEG-CORE орнату

pip install evileg-core

Сондай-ақ, evileg_core осы пакетке қажетті барлық тәуелділіктерді тартады. Соның ішінде redis -мен жұмыс істеу үшін пайдаланылатын django-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",
        }
    }
}

Үлгі_кэштелген_сипатты пайдалану

Қалыпты кэштеу

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 секунд ішінде кэштейді. Келесі жолы мақала беті сұралғанда, сұрау алдымен белгілі бір мақала нысанының кэшіне жасалады және кэштің мерзімі өткен жағдайда ғана сұрау дерекқорға қайта жасалады.

Кэштеу уақытын орнату

Белгілі бір кэш уақытын орнатқыңыз келсе, декоратормен тайм-аут аргументін пайдалануға болады.

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 -дан мұраланған сыныптарда пайдалануға болады.
  • аргументтерге байланысты үлгі қасиеттерін кэштеу тек бірегей енгізу аргументтері үшін орындалуы керек, әйтпесе кэштеу дұрыс емес болады.
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

МК
  • Қар. 6, 2019, 2:25 Т.Ж.

а functools.lru_cache в данном случае не поможет?

Evgenii Legotckoi
  • Қар. 6, 2019, 3:16 Т.Ж.
  • (өңделген)

Добрый день.

Думаю, что не совсем. Технически здесь решается задача кэширования не последних вызовов функции, как в lru_cache, а кэширование свойств для ряда объектов модели данных. К тому же cache_clear() будет полностью удалять весь кэш, тогда как у меня предусмотрен более специфический функционал для инвалидации части ключей, которые перестали быть актуальны.

Давайте поясню на примере.

На сайте есть модель данных ForumTopic , у которой есть лайки и дислайки, а также они подсвечиваются, если пользователь выбрал лайк или дислайк. Вся эта информация у меня кэшируется, поскольку для лайков и дислайков используются GenericForeignKey и запросы к базе данных посылаются отдельно, что получается несколько накладно для страниц со списком тем на форуме. Поэтому я предпочитаю кэшировать эти данные и при срабатывание некоторых событий делать инвалидацию кэша.

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

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

Когда вы вызываете функцию invalidate_model_cached_property, то кэш очищается только для конкретного объекта базы данных.

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

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

Но если я что-то не учёл и у вас есть, что дополнить, то с удовольствием выслушаю вашу точку зрения, возможно, что это поможет доработать функциональность model_cached_property

NSProject
  • Мамыр 27, 2022, 6:27 Т.Ж.
  • (өңделген)

Всё конечно супер классно. Интересует лишь один вопрос.

NSProject
  • Мамыр 28, 2022, 10:20 Т.Ж.

Здравствуйте. В общем меня интересует такой вопрос. Я пробовал это на Like , Dislike. Как я понимаю если не перевалидировать кеш то ничего не изменится на странице. Вернётся значение из кэша? Отсюда второй вопрос как и где прописть эту перевалидацию? Ибо если я пишу её через модель как сказано в статье. То ничего не происходит. По этому интересует то как и где перевалидировать кеш.

Evgenii Legotckoi
  • Мамыр 30, 2022, 10:25 Т.Ж.

Да, если не вызывать invalidate_cache , то ничего не произойдёт.
Место вызова инвалидации обычно индивидуально. Но я стараюсь вешать его на сигналы сохранения и удаления объектов.

В случае с Like Dislike , которые используют GenericForeignKey удобнее всего поступить следующим образом.

Добавить метод invalidate_cache , который будет вызывать метод инвалидации content_object

class LikeDislike(...):

    ...

    def invalidate_cache(self):
        self.content_object.invalidate_like_dislike_cache()

А потом навешать инвалидацию на сигналы

# -*- coding: utf-8 -*-

from django.db.models.signals import post_save, pre_delete

from .models import LikeDislike

def cache_invalidate_activity(sender, instance, **kwargs):
    instance.invalidate_cache()

post_save.connect(cache_invalidate_activity, sender=LikeDislike)
pre_delete.connect(cache_invalidate_activity, sender=LikeDislike)

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

NSProject
  • Маусым 2, 2022, 9:33 Т.Ж.

Спасибо за пояснения. Я ток щас догнал как это всё работает. Просто с сигналами не работал никогда. Но вот теперь стало понятно.

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:50ұпай,
  • Бағалау ұпайлары-4
m
  • molni99
  • Қаз. 26, 2024, 1:37 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:80ұпай,
  • Бағалау ұпайлары4
m
  • molni99
  • Қаз. 26, 2024, 1:29 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:20ұпай,
  • Бағалау ұпайлары-10
Соңғы пікірлер
ИМ
Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Енді форумда талқылаңыз
m
moogoҚар. 22, 2024, 7:17 Т.Ж.
Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectМаусым 4, 2022, 3:49 Т.Ж.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

Бізді әлеуметтік желілерде бақылаңыз