Django template slow to render: кэширование помогает последующим загрузкам, но можно ли помочь первой?

У меня есть приложение django, размещенное на heroku, и у меня есть страница "семейный альбом", которая загружает кучу миниатюр изображений, которые ссылаются на большую страницу с подробными изображениями. (Причем набор изображений может быть разным для каждого пользователя).

Каждая из этих миниатюр использует шаблон image_link.html. Максимум на странице семейного альбома может быть до ~1100 таких миниатюр, и они отлично загружаются в продакшене.

Проблема: я хотел добавить возможность небольшого наведения курсора, чтобы при наведении курсора на миниатюру можно было увидеть наложение того, кто изображен на картинке. (Это возвращается функцией класса Image). Я начал с кода наложения изображения из w3schools здесь , и обновил его, чтобы показать список людей на каждой фотографии (вместо статичного текста).

Это работает отлично, но локально загрузка страницы занимает около 4-5 секунд, а когда я развертываю ее на продакшене (на heroku), это занимает вечность: в среднем ~22 секунды, иногда превышая 30-секундный таймаут. (Я использую один Hobby Dyno).

Так что я сделал несколько вещей:

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

Это делает последующие загрузки быстрыми, но первая - просто убийца. Я относительно новичок в кэшировании в django- есть ли другие вещи, которые я могу сделать, чтобы ускорить это? Например, могу ли я как-то отрисовать шаблон в фоновом режиме до того, как пользователь запросит его?

Вот код: image_index.html (он же "семейный альбом"):

{% extends 'familytree/base.html' %}
{% block title %} - family album{% endblock title %}
{% block content %}
{% load cache %}

{% cache 1800 sidebar user %}

<h1>Family Album</h1>
{% if image_list %}
    {% for image in image_list %}
        {% include "familytree/image_link.html" with image=image height=150 show_hover=True %}
    {% endfor %}
{% else %}
    <p>No images are available.</p>
{% endif %}


{% endcache %}
{% endblock content %}

image_link.html (новый бит - это наложение span в блоке 'if show_hover'):

    <div style="display: inline-block; margin-bottom:10px"; class="image_container">
    <a href="{% url 'image_detail' image.id  %}">
        {%  if image.little_name %}
            <img src="{{ media_server }}/image/upload/h_{{ height }},r_20/{{ image.little_name }}" class="image"/>
        {%  else %}
            <img src="{{ media_server }}/image/upload/h_{{ height }},r_20/{{ image.big_name }}" class="image"/>
        {%  endif %}

        {% if show_hover %}
            <span class="overlay">
                <span class="text">Pictured: {{image.pictured_list}}</span>
            </span>
        {%  endif %}

        <div style="padding-left: 8px">
        {%  if image.year %}
            ({{ image.year }})
        {%  endif %}
        </div>
    </a>
</div>

И заранее я вызываю эту функцию в views.py, когда пользователь только приходит, так что я могу просто передать ее в image_index, когда он туда зайдет:

def get_image_index_stuff(accessible_branches, profile):
image_list = Image.objects.none()
for branch in accessible_branches:
    name = branch.display_name
    image_list = image_list.union(Image.objects.filter(branches__display_name__contains=name).order_by('year'))
sorted_list = image_list.order_by('year')

image_cache_name = 'images_' + str(profile.user)
cache.set(image_cache_name, sorted_list, 60 * 30)  # save this for 30 minutes
return sorted_list

Вот стили для наложения и изображения:

    /*Stuff for image gallery hover text:*/
.image_container {
  position: relative;
}

.image {
  display: block;
  width: 100%;
  height: auto;
}

.overlay {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  height: 100%;
  width: 100%;
  opacity: 0;
  transition: .5s ease;
  background-color: var(--link-color);
  border-radius: 20px;
}

.image_container:hover .overlay {
  opacity: 1;
}

.text {
  color: white;
  font-size: 12px;
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  text-align: center;
}

Некоторые предложения:

  1. Делегируйте создание кэша на обработчик фонового процесса, например celery
  2. .
  3. Если вы хотите отобразить длинную страницу, попробуйте сделать бесконечную прокрутку страниц, подобную facebook, чтобы создать иллюзию, что у вас есть длинная страница, но при этом страницы отображаются в фоновом режиме.
Вернуться на верх