Продвинутый Django 5 для продолжающих

Прогресс по курсу:  0/193

10.3 Уровни кэша в Django
7 из 16 шагов пройдено
0 из 27 баллов  получено

В прошлом шаге мы написали код для извлечения ключа из кэша (и добавления в случае отсутствия), такой способ не совсем удобен для применения.

Для этого есть более простой и красивый способ - использовать метод get_or_set(key, default, timeout).

Наш прошлый код:

    book_list = cache.get('cached_book_list')
    if not book_list:
        book_list = Book.objects.all()
        cache.set('cached_book_list', book_list)


Будет заменён всего на одну строку:

    book_list = cache.get_or_set('cached_book_list', Book.objects.all())


В результате представление будет выглядеть так:

@require_http_methods(['GET'])
def book_list(request):
    book_list = cache.get_or_set('cached_book_list', Book.objects.all())
    form = BookCreateForm(auto_id=False)
    return render(request, 'base.html', {'book_list': book_list, 'form': form})


Снова перейдём на страницу проекта :


При повторном:

Сейчас используется только одна команда get_or_set, как при первом обращении к кэшу(создании ключа), так и при последующих.

В этом примере на запрос на извлечение элемента из кэша требуется больше времени (0,64мс), чем время, сэкономленное на SQL-запросе (0,37мс). В ситуациях когда сайт использует много SQL-запросов и к нему будет обращаться большое число пользователей, вы обнаружите значительное сокращение времени за счет извлечения данных из кэша, без обращения к базе данных, и вы сможете раздавать сайт большему числу пользователей. Поочередные запросы к одному и тому же URL-адресу будут извлекать данные из кэша.

При кэшировании данных с помощью cache.get_or_set('cached_book_list', Book.objects.all()) в представлении book_list() тайм-аут указан не был, в этом случае будет использоваться тайм-аут, принятый по умолчанию (300 секунд).

По истечении тайм-аута следующий запрос к URL-адресу вызовет промах кэша, будет исполнен набор запросов QuerySet, и данные будут снова кэшированы еще на 5 минут. При этом в элементе TIMEOUT настроечного параметра CACHES можно определять другой тайм-аут, который будет использоваться по умолчанию.

Так-же могут быть ситуации, когда необходимо оперативно обновить кэшированные данные, не дожидаясь истечения тайм-аута. В нашем проекте это происходит при каждом добавлении, удалении, редактировании книги или изменения статуса книги. При этом данные ключа cached_book_list устаревают, необходимо его удалить. Для этого рассмотрим метод удаления ключа - delete(key).

Доработаем соответствующие представления, для этого отредактируем файл views.py приложения books:

@require_http_methods(['POST'])
def create_book(request):
    form = BookCreateForm(request.POST)
    if form.is_valid:
        book = form.save()
        cache.delete('cached_book_list')
    return render(request, 'partial_book_detail.html', {'book': book})
def update_book_details(request, pk):
    book = Book.objects.get(pk=pk)
    if request.method == 'POST':
        form = BookEditForm(request.POST, instance=book)
        if form.is_valid():
            book = form.save()
            cache.delete('cached_book_list')
            return render(request, 'partial_book_detail.html', {'book': book})
    else:
        form = BookEditForm(instance=book)
    return render(request, 'partial_book_update_form.html', {'book': book, 'form': form})
@require_http_methods(['DELETE'])
def delete_book(request, pk):
    book = get_object_or_404(Book, pk=pk)
    book.delete()
    cache.delete('cached_book_list')
    return HttpResponse()
@require_http_methods(['PUT'])
def update_book_status(request, pk):
    book = get_object_or_404(Book, pk=pk)
    if book.read:
        book.read = False
    else:
        book.read = True
    book.save()
    cache.delete('cached_book_list')
    return render(request, 'partial_book_detail.html', {'book': book})


После этого перейдём на страницу проекта и изменим статус любой книги:

Команда delete показывает что ключ cached_book_list с устаревшими данными был удалён.

При следующем обновлении страницы он снова будет создан, уже с актуальными данными.


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

Получается, если вью классовая, то просто 

queryset = cache.get_or_set('cached_book_list', Book.objects.all()) ?

@Ilia_Boiarintsev, да, верно.

тут опечатка у нас нет приложения django_htmx

наше приложение называется books

Доработаем соответствующие представления, для этого отредактируем файл views.py приложения django_htmx:

@require_http_methods(['POST'])
def create_book(request):
    form = BookCreateForm(request.POST)
    if form.is_valid:
        book = form.save()
        cache.delete('cached_book_list')
    return render(request, 'partial_book_detail.html', {'book': book})

@No_Name, спасибо, исправил.