В прошлом шаге мы написали код для извлечения ключа из кэша (и добавления в случае отсутствия), такой способ не совсем удобен для применения.
Для этого есть более простой и красивый способ - использовать метод 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 с устаревшими данными был удалён.
При следующем обновлении страницы он снова будет создан, уже с актуальными данными.