Рефакторинг шаблонов

У нас накопилась достаточно большая библиотека шаблонов, в которых выводятся записи:
  • Главная страница
  • Страница сообщества
  • Страница профайла
  • Страница просмотра отдельной записи
В шаблонах повторяются похожие куски кода, которые выводят текст записи с картинкой и ссылками на дополнительные элементы. Для создания новой страницы вы копировали один и тот же фрагмент шаблона. Но если захочется отредактировать HTML-код, в котором выводится пост — вам придется внести исправления в несколько разных шаблонов и наверняка вы забудете о каком-нибудь из них.
Если у разработчика уходит много времени на повторяющиеся действия — это неправильно. Состояние проекта, когда уже отчетливо чувствуется, что пришло время навести порядок в коде, называется «технический долг». Это естественный этап развития проекта, не зря для него придумали отдельный термин.
Проведём рефакторинг проекта. Для начала вынесем код отдельного поста в собственный шаблон, и затем будем встраивать его всюду, где нужно вывести пост.
Создайте шаблон post_item.html с таким содержимым:
Скопировать кодHTML
<div class="card mb-3 mt-1 shadow-sm"> <!-- Отображение картинки --> {% load thumbnail %} {% thumbnail post.image "960x339" crop="center" upscale=True as im %} <img class="card-img" src="{{ im.url }}" /> {% endthumbnail %} <!-- Отображение текста поста --> <div class="card-body"> <p class="card-text"> <!-- Ссылка на автора через @ --> <a name="post_{{ post.id }}" href="{% url 'profile' post.author.username %}"> <strong class="d-block text-gray-dark">@{{ post.author }}</strong> </a> {{ post.text|linebreaksbr }} </p> <!-- Если пост относится к какому-нибудь сообществу, то отобразим ссылку на него через # --> {% if post.group %} <a class="card-link muted" href="{% url 'group' post.group.slug %}"> <strong class="d-block text-gray-dark">#{{ post.group.title }}</strong> </a> {% endif %} <!-- Отображение ссылки на комментарии --> <div class="d-flex justify-content-between align-items-center"> <div class="btn-group "> <a class="btn btn-sm text-muted" href="{% url 'post' post.author.username post.id %}" role="button"> {% if post.comments.exists %} {{ post.comments.count }} комментариев {% else%} Добавить комментарий {% endif %} </a> <!-- Ссылка на редактирование поста для автора --> {% if user == post.author %} <a class="btn btn-sm text-muted" href="{% url 'post_edit' post.author.username post.id %}" role="button"> Редактировать </a> {% endif %} </div> <!-- Дата публикации поста --> <small class="text-muted">{{ post.pub_date }}</small> </div> </div> </div>
Теперь во всех шаблонах код отдельной записи замените на include нового шаблона:
Скопировать кодHTML
{% include "post_item.html" with post=post %}
Переменная post — это объект с записью.
Чтобы у вас не слетела верстка — вот шаблон главной страницы проекта со внесёнными изменениями:
Скопировать кодHTML
{% extends "base.html" %} {% block title %} Последние обновления {% endblock %} {% block content %} <div class="container"> <h1> Последние обновления на сайте</h1> <!-- Вывод ленты записей --> {% for post in page %} <!-- Вот он, новый include! --> {% include "post_item.html" with post=post %} {% endfor %} </div> <!-- Вывод паджинатора --> {% if page.has_other_pages %} {% include "paginator.html" with items=page paginator=paginator%} {% endif %} {% endblock %}
На примере этой страницы вы без проблем обновите все остальные шаблоны, где выводятся записи.

Задание

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