Django Highlights: создание шаблонов строк сохранения (часть 2)
Опубликовано: 2022-03-10Некоторые простые подходы к созданию веб-сайтов требуют от разработчика написания каждой строки HTML вручную. С другой стороны, коммерческие конструкторы сайтов без кода создают весь HTML-код для пользователя автоматически, часто за счет удобочитаемости результирующего кода. Шаблоны находятся примерно в середине этого спектра, но ближе к написанному от руки HTML, чем, скажем, создание структуры страницы в одностраничном приложении с использованием React или подобной библиотеки. Это приятное место в континууме обеспечивает многие преимущества ручного HTML-кода с нуля (семантический / читаемый код, полный контроль над структурой страницы, быстрая загрузка страниц) и добавляет разделение проблем и лаконичность, все за счет затрат некоторого времени на написание измененный HTML вручную. В этой статье демонстрируется использование шаблонов Django для написания сложных страниц.
Сегодняшняя тема выходит за рамки Django. Flask (еще один веб-фреймворк) и Pelican (генератор статических сайтов) — это лишь два из многих других проектов Python, в которых используется тот же подход к шаблонам. Jinja2 — это механизм шаблонов, который используют все три фреймворка, хотя вы можете использовать другой, изменив настройки проекта (строго говоря, Jinja2 — это расширенный набор шаблонов Django). Это автономная библиотека, которую вы можете включать в свои проекты даже без фреймворка, поэтому методы, описанные в этой статье, широко полезны.
Предыдущие части серии:
- Особенности Django: пользовательские модели и аутентификация (часть 1)
- Особенности Django: модели, администрирование и использование реляционной базы данных (часть 3)
- Основные моменты Django: работа со статическими активами и медиафайлами (часть 4)
Рендеринг на стороне сервера
Шаблон — это просто файл HTML, в котором HTML расширен дополнительными символами. Помните, что означает HTML : язык гипертекстовой разметки . Jinja2, наш язык шаблонов, просто добавляет к языку дополнительные осмысленные символы разметки. Эти дополнительные структуры интерпретируются, когда сервер отображает шаблон для предоставления пользователю простой HTML-страницы (то есть дополнительные символы из языка шаблонов не попадают в окончательный вывод).
Рендеринг на стороне сервера — это процесс создания веб-страницы в ответ на запрос. Django использует рендеринг на стороне сервера для предоставления клиенту HTML-страниц. В конце своего выполнения функция просмотра объединяет HTTP-запрос, один или несколько шаблонов и, при необходимости, данные, полученные во время выполнения функции, для создания одной HTML-страницы, которую она отправляет в качестве ответа клиенту. Данные поступают из базы данных через представление в шаблон, чтобы попасть к пользователю. Не волнуйтесь, если это абстрактное объяснение не имеет смысла, мы обратимся к конкретному примеру в оставшейся части этой статьи.
Настройка
В нашем примере мы возьмем довольно сложную веб-страницу, запустим шаблон администратора Bootstrap и перепишем HTML как шаблон Jinja2. Обратите внимание, что библиотека с лицензией MIT использует другую систему шаблонов (основанную на JavaScript и Pug) для создания страницы, которую вы видите, но их подход существенно отличается от шаблонов в стиле Jinja2, поэтому этот пример является скорее обратным проектированием, чем переводом. их отличного проекта с открытым исходным кодом. Чтобы увидеть веб-страницу, которую мы будем создавать, вы можете взглянуть на предварительный просмотр Start Bootstrap в реальном времени.
Я подготовил образец заявления для этой статьи. Чтобы запустить проект Django на своем компьютере, запустите виртуальную среду Python 3 и выполните следующие команды:
pip install django git clone https://github.com/philipkiely/sm_dh_2_dashboard.git cd sm_dh_2_dashboard python manage.py migrate python manage.py createsuperuser python manage.py loaddata employee_fixture.json python manage.py runserver
Затем откройте веб-браузер и перейдите по https://127.0.0.1:8000
. Вы должны увидеть ту же страницу, что и в предварительном просмотре, соответствующую изображению ниже.
Поскольку это руководство сосредоточено на внешнем интерфейсе, базовое приложение Django очень простое. Это может показаться сложной конфигурацией для представления одной веб-страницы, и, честно говоря, так оно и есть. Тем не менее, такая обширная настройка может также поддерживать гораздо более надежное приложение.
Теперь мы готовы пройти через процесс превращения этого 668-строчного HTML-файла в сайт Django с правильной архитектурой.
Шаблоны и наследование
Первым шагом в рефакторинге сотен строк HTML в чистый код является разделение элементов на собственные шаблоны, которые Django объединит в одну веб-страницу на этапе рендеринга.
Посмотрите на страницы/шаблоны . Вы должны увидеть пять файлов:
- base.html , базовый шаблон, который будет расширяться каждой веб-страницей. Он содержит
<head>
с заголовком, импорт CSS и т. д. - navbar.html , HTML для верхней навигационной панели, компонент, который необходимо включать при необходимости.
- footer.html , код для нижнего колонтитула страницы, еще один компонент, который нужно включить при необходимости.
- sidebar.html , HTML-код для боковой панели, третий компонент, который будет включен при необходимости.
- index.html , код, уникальный для главной страницы. Этот шаблон расширяет базовый шаблон и включает в себя три компонента.
Django собирает эти пять файлов, как и Voltron, для отображения индексной страницы. Это позволяют ключевые слова {% block %}
, {% include %}
и {% extend %}
. В base.html :
{% block content %} {% endblock %}
Эти две строки оставляют место для других шаблонов, расширяющих base.html , для вставки собственного HTML. Обратите внимание, что content
— это имя переменной, вы можете иметь несколько блоков с разными именами в шаблоне, что дает гибкость дочерним шаблонам. Мы видим, как расширить это в index.html :
{% extends "base.html" %} {% block content %} <!-- HTML Goes Here --> {% endblock %}
Использование ключевого слова extends
с именем базового шаблона дает индексной странице ее структуру, избавляя нас от копирования в заголовке (обратите внимание, что имя файла является относительным путем в виде строки в двойных кавычках). Индексная страница включает в себя все три компонента, которые являются общими для большинства страниц сайта. Мы добавляем эти компоненты с include
тегами, как показано ниже:
{% extends "base.html" %} {% block content %} {% include "navbar.html" %} {% include "sidebar.html" %} <!--Index-Specific HTML--> {% include "footer.html" %} <!--More Index-Specific HTML--> {% endblock %}
В целом, эта структура обеспечивает три ключевых преимущества по сравнению с написанием страниц по отдельности:
- СУХОЙ (не повторяйтесь) код
Вынося общий код в определенные файлы, мы можем изменить код только в одном месте и отразить эти изменения на всех страницах. - Повышенная читабельность
Вместо того, чтобы прокручивать один гигантский файл, вы можете изолировать конкретный интересующий вас компонент. - Разделение ответственности
Код, скажем, для боковой панели теперь должен быть в одном месте, не должно быть каких-либо мошеннических теговscript
плавающих внизу кода, или других помех между тем, что должно быть отдельными компонентами. Факторизация отдельных частей требует хорошей практики кодирования.
Хотя мы могли бы сэкономить еще больше строк кода, поместив определенные компоненты в шаблон base.html , разделение их дает два преимущества. Во-первых, мы можем встроить их именно там, где они должны находиться в одном блоке (это относится только к footer.html , который находится внутри основного div
блока content
). Другое преимущество заключается в том, что если бы мы создали страницу, скажем, страницу с ошибкой 404, и нам не нужна боковая панель или нижний колонтитул, мы могли бы их не использовать.
Эти возможности являются нормой для шаблонов. Теперь мы обратимся к мощным тегам, которые мы можем использовать в нашем index.html для предоставления динамических функций и экономии сотен строк кода.
Два фундаментальных тега
Это далеко не исчерпывающий список доступных тегов. Документация Django по шаблонам предоставляет такое перечисление. Сейчас мы сосредоточимся на вариантах использования двух наиболее распространенных элементов языка шаблонов. В своей работе я в основном использую только теги for
и if
на регулярной основе, хотя дюжина или более других тегов имеют свои собственные варианты использования, которые я рекомендую вам просмотреть в справочнике по шаблонам.
Прежде чем мы перейдем к тегам, я хочу сделать замечание о синтаксисе. Тег {% foo %}
означает, что «foo» — это функция или другая возможность самой системы шаблонов, а тег {{ bar }}
означает, что «bar» — это переменная, переданная в конкретный шаблон.
Для циклов
В оставшемся index.html самым большим разделом кода на несколько сотен строк является таблица. Вместо этой жестко закодированной таблицы мы можем динамически генерировать таблицу из базы данных. Вспомните python manage.py loaddata employee_fixture.json
из этапа настройки. Эта команда использовала файл JSON, называемый Django Fixture, для загрузки всех 57 записей о сотрудниках в базу данных приложения. Мы используем представление в views.py для передачи этих данных в шаблон:
from django.shortcuts import render from .models import Employee def index(request): return render(request, "index.html", {"employees": Employee.objects.all()})
Третий позиционный аргумент для render
— это словарь данных, доступный для шаблона. Мы используем эти данные и тег for
для построения таблицы. Даже в исходном шаблоне, из которого я адаптировал эту веб-страницу, таблица сотрудников была жестко запрограммирована. Наш новый подход сокращает сотни строк повторяющихся жестко закодированных строк таблицы. index.html теперь содержит:
{% for employee in employees %} <trv <td>{{ employee.name }}</td> <td>{{ employee.position }}</td> <td>{{ employee.office }}</td> <td>{{ employee.age }}</td> vtd>{{ employee.start_date }}</td> <td>${{ employee.salary }}</td> </tr> {% endfor %}
Большим преимуществом является то, что это значительно упрощает процесс обновления таблицы. Вместо того, чтобы разработчик вручную редактировал HTML-код, чтобы отразить повышение заработной платы или нового сотрудника, а затем внедрял это изменение в рабочую среду, любой администратор может использовать панель администратора для внесения обновлений в режиме реального времени (https://127.0.0.1/admin, используйте учетные данные, созданные с помощью python manage.py createsuperuser
, создают суперпользователя для доступа). Это преимущество использования Django с этим движком рендеринга вместо того, чтобы использовать его отдельно в генераторе статических сайтов или другом подходе к шаблонам.
Если еще
Тег if
— невероятно мощный тег, который позволяет вам оценивать выражения в шаблоне и соответствующим образом корректировать HTML. Такие строки, как {% if 1 == 2 %}
, вполне допустимы, хотя и немного бесполезны, поскольку они каждый раз дают один и тот же результат. Где сияет тег if
, так это при взаимодействии с данными, переданными в шаблон представлением. Рассмотрим следующий пример из sidebar.html :
<div class="sb-sidenav-footer"> <div class="small"> Logged in as: </div> {% if user.is_authenticated %} {{ user.username }} {% else %} Start Bootstrap {% endif %} </div>
Обратите внимание, что весь пользовательский объект передается в шаблон по умолчанию, и мы ничего не указываем в представлении, чтобы это произошло. Это позволяет нам получить доступ к статусу аутентификации пользователя (или его отсутствию), имени пользователя и другим функциям, включая следующие отношения внешнего ключа для доступа к данным, хранящимся в профиле пользователя или другой подключенной модели, все из файла HTML.
Вы можете быть обеспокоены тем, что этот уровень доступа может представлять угрозу безопасности. Однако помните, что эти шаблоны предназначены для фреймворка рендеринга на стороне сервера. После создания страницы теги уничтожаются и заменяются чистым HTML. Таким образом, если оператор if
вводит данные на страницу при некоторых условиях, но данные не используются в данном экземпляре, то эти данные вообще не будут отправлены клиенту, поскольку оператор if
оценивается на стороне сервера. Это означает, что правильно построенный шаблон является очень безопасным методом добавления конфиденциальных данных на страницы без того, чтобы эти данные покидали сервер без необходимости. Тем не менее, использование шаблонов Django не устраняет необходимость передавать конфиденциальную информацию безопасным и зашифрованным способом, это просто означает, что проверки безопасности, такие как user.is_authenticated
могут безопасно выполняться в HTML, когда он обрабатывается на стороне сервера.
Эта функция имеет ряд других вариантов использования. Например, на общей домашней странице продукта вы можете скрыть кнопки «Зарегистрироваться» и «Войти» и заменить их кнопкой «Выйти» для вошедших пользователей. Другое распространенное использование — отображение и скрытие сообщений об успешном завершении или ошибке для таких операций, как отправка формы. Обратите внимание, что, как правило, вы не будете скрывать всю страницу, если пользователь не вошел в систему. Лучший способ изменить всю веб-страницу на основе статуса аутентификации пользователя — это обработать ее в соответствующей функции в views.py .
Фильтрация
Частью работы представления является правильное форматирование данных для страницы. Для этого у нас есть мощное расширение для тегов: фильтры. В Django доступно множество фильтров для выполнения таких действий, как выравнивание текста по ширине, форматирование дат и добавление чисел. По сути, вы можете думать о фильтре как о функции, которая применяется к переменной в теге. Например, мы хотим, чтобы наши цифры зарплаты читались как «1 200 000 долларов США» вместо «1 200 000». Мы будем использовать фильтр, чтобы выполнить работу в index.html :
<td>${{ employee.salary|intcomma }}</td>
Характер трубы |
это фильтр, который применяет команду intcomma
к переменной employee.salary
. Символ «$» идет не из шаблона, для такого элемента, который появляется каждый раз, проще просто вставить его за пределы тега.
Обратите внимание, что intcomma
требует, чтобы мы включили {% load humanize %}
вверху нашего index.html и 'django.contrib.humanize',
в наших INSTALLED_APPS
в settings.py . Это делается для вас в предоставленном образце приложения.
Заключение
Рендеринг на стороне сервера с помощью движка Jinja2 предоставляет ключевые инструменты для создания чистого, адаптируемого и отзывчивого внешнего кода. Разделение страниц на файлы позволяет создавать СУХИЕ компоненты с гибкой композицией. Теги предоставляют основные возможности для отображения данных, переданных из базы данных функциями просмотра. При правильном подходе этот подход может повысить скорость, возможности SEO, безопасность и удобство использования сайта и является ключевым аспектом программирования в Django и подобных фреймворках.
Если вы еще этого не сделали, ознакомьтесь с образцом приложения и попробуйте добавить собственные теги и фильтры, используя полный список.
Django Highlights — это серия, знакомящая с важными концепциями веб-разработки в Django. Каждая статья написана как отдельное руководство по одному из аспектов разработки Django, предназначенное для того, чтобы помочь фронтенд-разработчикам и дизайнерам глубже понять «другую половину» кодовой базы. Эти статьи в основном созданы, чтобы помочь вам понять теорию и соглашения, но содержат некоторые примеры кода, написанные на Django 3.0.
Предыдущие части серии:
- Особенности Django: пользовательские модели и аутентификация (часть 1)
- Особенности Django: модели, администрирование и использование реляционной базы данных (часть 3)
- Основные моменты Django: работа со статическими активами и медиафайлами (часть 4)