Верстаем статический web-сайт с помощью Python3x, базовый шаблон
Jazz
Опубликован: | 2024-02-10T02:50:31.905062Z |
Отредактирован: | 2024-02-10T02:50:31.905062Z |
Статус: | публичный |
Продолжаем разработку sitefish - web-приложения для статического web-сайта. На текущий момент в проекте всё готово, чтобы наконец-то приступить к вёрстке страниц сайта. И в этом выпуске я покажу обычный способ, как можно избежать повторения html-кода при вёрстке страниц. На этом этапе разработки web-приложения будем верстать так называемый базовый шаблон. Поскольку проект построен на основе языка программирования Python3x, html-код страниц генерируется программой автоматически, в соответствии с логикой заданного для конкретного URL-адреса обработчика и по индивидуальному html-шаблону. В этом проекте шаблоны будут построены на основе Jinja2 - эта библиотека уже подключена в проект. Приступим...
Шаблоны Jinja2
Библиотеку Jinja2 я подключал в проект на начальном этапе конфигурации в файле __inint__.py
базового каталога sitefish. Эта библиотека предоставляет разработчику специальный синтаксис и целый набор полезных возможностей и разнообразных логических блоков, по ссылке в начале этого абзаца можно найти описание всего этого великолепия.
В этом цикле статей я рассказываю о разработке статического web-сайта, шаблоны sitefish буду содержать минимум специфических элементов Jinja2, в этой демонстрации я покажу только наследование и переопределение блоков - обычные инструменты, исключающие повторение html-кода.
Кроме этого, в проект подключена библиотека webassets, которая позволяет автоматизированно минимизировать код таблиц стилей и сценариев JavaScript в процессе обработки шаблона. Она добавляет в синтаксис Jinja2 собственный оригинальный блок, об этом чуть позже...
Построение базового шаблона
Работа над проектом прерывалась, поэтому следует восстановить рабочее окружение, для этого запускаю терминал, вхожу в нём в корневой каталог проекта.
$ cd ~/workspace/sitefish/
Активирую виртуальное окружение.
$ source venv/bin/activate
Все далее продемонстрированные команды я буду выполнять в этом терминале, находясь в корневом каталоге проекта.
Приступим к вёрстке базового шаблона. Обычно базовый шаблон верстается на основе макета сайта и состоит из базовых элементов, повторяющихся на всех типовых страницах. Как такового макета для sitefish у меня нет, ибо я не дизайнер, тем не менее определённый образ воображение рисует, этого образа я и буду придерживаться.
Создаю и открываю в текстовом редакторе файл базового шаблона, даю этому файлу соответствующее имя - base.html
, и размещаю его в каталоге templates
.
$ vim sitefish/templates/base.html
Пишу в этот файл следующий код.
<!DOCTYPE html>
<html lang="ru">
<head>
{% block metas %}
<meta charset="utf-8">
<meta http-equiv="X-UA-COMPATIBLE" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
{% endblock metas %}
<title>Sitefish: {% block title %}{% endblock title %}</title>
{% block styles %}
<link rel="icon" href="{{ url_for('favicon') }}"
type="image/vnd.microsoft.icon">
{% assets filters='cssmin', output='generic/css/vendor.css',
'vendor/bootstrap/css/bootstrap.css',
'vendor/bootstrap/css/bootstrap-theme.css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
{% endblock styles %}
</head>
<body></body>
</html>
Как видно, это обычный html-код. Внутри тега <head>
с помощью синтаксиса Jinja2 я выделил три блока:
-
блок
metas
содержит теги<meta>
; -
блок
title
модифицирует тег<title>
; -
блок
styles
содержит теги<link>
.
Внутри блока styles
выделен блок assets
, он имеет особый синтаксис и обрабатывается библиотекой webassets, в этом блоке я задал фильтр обработки - cssmin
, с помощью которого группируются таблицы стилей, адрес и имя файла в который записываются сгруппированные таблицы стилей, и список файлов, которые обрабатываются и группируются. Здесь я обрабатываю два файла из каталога vendor
- этот каталог уже существует и содержит сторонние библиотеки, результат обработки записываю в файл с именем vendor.css
.
Фильтр cssmin это специальная программа для минимизации CSS-кода, её нужно установить в виртуальное окружение. В процессе работы над шаблонами sitefish я буду использовать ещё один фильтр - rjsmin, устанавливаю эти пакеты.
$ pip install cssmin rjsmin
Все выделенные в разметке базового шаблона блоки впоследствии можно использовать в шаблонах конкретных страниц сайта, дополнять, при необходимости, или переопределять полностью. Все эти операции выполняются с помощью инструментов Jinja2.
В используемом макете сайта предусмотрены два общих для всех страниц элемента:
-
главное меню сайта - основной инструмент навигации по страницам;
-
нижняя панель страницы, обычно в сленге web-разработчиков её называют "подвал".
Главное меню сайта я воспроизведу при помощи соответствующих инструментов Bootstrap. На текущем этапе разработки меню будет иметь два пункта: ссылка на стартовую страницу сайта, совмещённая с логотипом, раздел с именем "Компания" с выпадающим меню. Вот как выглядит код этого элемента.
<nav id="navigation" class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand"
href="{{ url_for('index') }}">
<img alt="logo"
src="{{ url_for('static', path='images/logo.png') }}"
width="28"
height="28">
</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Компания <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li>
<a href="{{ url_for('page', page='about.html') }}">
О компании
</a>
</li>
<li>
<a href="{{ url_for('page', page='contacts.html') }}">
Контакты
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
Этот элемент размещаю внутри тега <body>
. Здесь следует обратить внимание на атрибут href
в тегах <a>
. URL-адреса я задаю с помощью вспомогательной функции url_for
, её я определил на стадии конфигурации проекта в файле __init__.py
. Точно так же задан атрибут src
в теге <img>
. Используемые с этой функцией параметры тоже определены в файле конфигурации.
В разметке главного меню нужно обратить внимание на классы dropdown
и dropdown-menu
, это библиотечные классы Bootstrap. С помощью этих классов впоследствии не составит труда добавить в меню дополнительные пункты и ссылки в них с URL-адресами новых страниц сайта.
Второй общий для всех страниц сайта элемент я сверстаю самостоятельно в теге <footer>
. Вот его код.
<footer id="footer">
<div class="container-fluid">
<div class="footer-block"></div>
<div class="footer-content">
<div class="footer-left text-left">
<img alt="right finger"
src="{{ url_for('static', path='images/footer-left.png') }}"
width="24"
height="24">
</div>
<div class="footer-center text-center">
<a id="footer-link"
href="{{ url_for('index') }}">
<span class="footer-link-text">Sitefish</span>
</a>
</div>
<div class="footer-right text-right">
<img alt="left finger"
src="{{ url_for('static', path='images/footer-right.png') }}"
width="24"
height="24">
</div>
<div class="footer-bottom"></div>
</div>
<div class="footer-bottom"></div>
</div>
</footer>
Этот элемент размещаю в теге <body>
под главным меню.
В базовый шаблон необходимо подключить используемые в проекте библиотеки JavaScript, их я выделю в отдельный блок соответствующим синтаксисом Jinja2 и webassets. Таким образом в шаблоне появляется ещё один блок - scripts
, и размещаю я его внутри тега <body>
под тегом <footer>
, вот как выглядит код этого блока.
{% block scripts %}
{% assets filters='rjsmin', output='generic/js/vendor-pub.js',
'vendor/jquery.js',
'vendor/bootstrap/js/bootstrap.js',
'vendor/luxon.js' %}
<script src="{{ ASSET_URL }}"></script>
{% endassets %}
{% endblock scripts %}
Внутри тегов <nav>
и <footer>
я использовал изображения, поскольку для sitefish я использую макет сайта CodeJ, эти изображения я скопирую прямо с сайта в каталог images
. Вот как выглядит дерево корневого каталога sitefish после этой операции.
Базовый шаблон для сайта является общим, и его я буду использовать для вёрстки html-файлов всех страниц сайта.
Верстаем страницы сайта
На текущий момент у сайта уже есть три страницы, их html-файлы хранятся в базовом каталоге templates
. Начнём с главной страницы - Index Page.
Открываю в текстовом редакторе файл index.html
.
$ vim sitefish/templates/main/index.html
Удаляю весь существующий на данный момент код и заменяю его следующим.
{% extends "base.html" %}
{% block title %}Index{% endblock title %}
Здесь я опять использовал синтаксис Jinja2, указал шаблонизатору имя базового шаблона с помощью выражения extends
и определил содержание тега <title>
в одноимённом блоке. Настало время протестировать этот код. Запускаю в терминале отладочный сервер.
$ python runserver.py
Запускаю браузер, в моём случае это Chromium, и стучусь в нём по адресу стартовой страницы - localhost:5000
.
В этом экземпляре браузера я буду отлаживать код страниц сайта, мне нужно, чтобы браузер не записывал используемые на страницах файлы в свой кеш. Отключить запись кеша можно в инструментах разработчика, в Chromium доступ к ним можно получить с помощью сочетания crtl+shift+i
. В окне инструментов разработчика перехожу на вкладку "Сеть" и ставлю флаг в поле "Отключить кеш".
Как видно на снимке экрана выше, на странице появились определённые в базовом шаблоне элементы, но выглядят они не совсем так, как мне хотелось бы, это легко исправить, для этого в шаблоне index.html
переопределяю блок styles
, дописываю в конец файла следующий код.
{% block styles %}
{{ super() }}
{% assets filters='cssmin', output='generic/css/main/index.css',
'css/base.css' %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
<link rel="canonical" href="{{ url_for('index') }}">
{% endblock styles %}
Внутри этого блока я использовал функцию super
, функция включает все определённые в соответствующем блоке базового шаблона теги, и дополнительный блок assets
, в котором сгруппировал файл таблиц стилей index.css
. Список файлов, из которых группируется index.css
, пока включает в себя один единственный файл - base.css
. Он определяет оформление общих для всех страниц сайта элементов макета. Чуть позже, при окончательной вёрстке, я добавлю в этот список другие CSS-файлы по мере необходимости. Создаю этот файл и открываю его в текстовом редакторе.
$ vim sitefish/static/css/base.css
В него пишу следующий код.
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 90px;
font-size: 12pt;
}
#navigation {
margin: 0;
border: 1px solid #d3d3d3;
background-image: linear-gradient(to bottom, #fffef2, #f3f2e7);
box-shadow: 0 0 8px #d3d3d3;
color: #666666;
}
.navbar-brand {
padding-top: 10px;
}
#footer {
position: absolute;
bottom: 0;
width: 100%;
height: 90px;
box-shadow: 0 0 1px #333333;
background-color: #666666;
background-image: linear-gradient(to bottom, #666666, #333333);
}
.footer-block {
height: 30px;
}
.footer-left {
width: 5%;
float: left;
margin-top: 5px;
}
.footer-center {
width: 90%;
float: left;
padding-top: 4px;
color: white;
}
#footer-link {
color: white;
text-decoration: none;
text-shadow: 0 0 8px #d9dcec;
}
#footer-link:hover {
cursor: pointer;
text-shadow: 0 0 0 #d9dcec;
}
.footer-link-text {
font-style: italic;
}
.footer-right {
width: 5%;
float: left;
margin-top: 5px;
}
.footer-bottom {
clear: both;
}
Сохраняю все правки кода в файлы, перехожу в окно браузера и обновляю страницу.
На странице вижу главное меню и "подвал". В них две ссылки на главную страницу. В меню, кроме этого, есть ещё и раздел "Компания". Пробую нажать на него левой кнопкой мыши.
В этом разделе размещены ссылки на две другие страницы сайта. Чтобы и они выглядели подобным образом, нужно отредактировать их html-файлы.
Открываю в текстовом редакторе файл about.html
.
$ vim sitefish/templates/main/about.html
Удаляю весь код, написанный на предыдущем этапе разработки и заменяю его следующим.
{% extends "base.html" %}
{% block title %}О компании{% endblock title %}
{% block styles %}
{{ super() }}
{% assets filters='cssmin', output='generic/css/main/about.css',
'css/base.css' %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
{% endblock styles %}
Эта страница тоже является наследницей базового шаблона, в ней переопределён блок title
и блок styles
. Для группировки файла about.css
пока используется единственный файл base.css
, но я получаю возможность впоследствии добавлять в этот список другие файлы, для каждого нового элемента можно выделить собственный файл, и из этих файлов группировать стили каждой страницы, на которой эти элементы использованы. Таким образом можно избежать повторения кода.
Сохраняю изменения в файлы, перехожу в окно браузера и пробую воспользоваться главным меню, в разделе "Компания" перехожу по ссылке "О компании".
Как видно на снимке экрана, в окне браузера изменился адрес в адресной строке и текст в заголовке, но страница выглядит точно также, как и предыдущая.
У сайта в текущей редакции есть ещё одна страница, её html-файл тоже нужно переписать. Открываю его в текстовом редакторе.
$ vim sitefish/templates/main/contacts.html
Опять удаляю весь код и заменяю его следующим.
{% extends "base.html" %}
{% block title %}Контакты{% endblock title %}
{% block styles %}
{{ super() }}
{% assets filters='cssmin', output='generic/css/main/contacts.css',
'css/base.css' %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
{% endblock styles %}
Этот шаблон опять наследует базовый шаблон, в нём переопределены блоки title
и styles
. Сохраняю изменения в файл, перехожу в окно браузера и с помощью ссылки в главном меню сайта перехожу на страницу "Контакты".
Все три снимка экрана демонстрируют, что страницы сайта в текущей редакции повторяю оформление макета и выглядят аналогичным образом. Базовый шаблон свёрстан, и я получаю возможность сосредоточиться на вёрстке каждой отдельной страницы, изменяя и дополняя её шаблон.
Управление webassets
Как известно, современные браузеры умеют показывать не только страницы сайтов, но и исходный код этих страниц. При разработке и тестировании сайта очень часто возникает потребность заглянуть в исходный код, дабы убедиться, что интерпретация шаблона происходит в полном соответствии с замыслом разработчика. Прямо сейчас меня интересует состояния тегов <link>
и <script>
. Находясь в окне браузера жму правую кнопку мыши и в контекстном меню выбираю пункт "Просмотр кода страницы", как альтернатива - можно воспользоваться клавиатурным сочетанием ctrl+u
. В результате оказываюсь на вкладке с исходным кодом страницы. Меня интересуют теги <link>
.
Обращаю внимание, что в этих тегах числятся файлы bootstrap.css
, bootstrap-theme.css
и base.css
. Первые два тега определены в базовом шаблоне, а последний в шаблоне данной конкретной страницы. Если перейти по ссылкам в этих тегах, можно убедиться, что код файлов CSS транслируется на страницу в неизменном виде. Но мне нужно этот код минимизировать. Как?
На стадии конфигурации проекта я подключил в файле конфигурации библиотеку webassets - именно эта библиотека управляет обработкой статических файлов, и в файле настроек на текущий момент присутствует опция ASSETS_DEBUG
. Что ж, давайте поменяем значение этой опции. Открываю файл настроек приложения.
$ vim .env
И модифицирую его код следующим образом.
DEBUG=True
ASSETS_DEBUG=False
Сохраняю изменения в файл. Останавливаю отладочный сервер, для этого окно терминала в котором сервер запущен делаю активным и жму ctrl+c
. Вновь запускаю сервер.
$ python runserver.py
Каждая правка файла настроек должна сопровождаться перезапуском отладочного сервера, чтобы внесённые изменения вступили в силу. Перехожу в окно браузера, обновляю вкладку с исходным кодом открытой страницы и обращаю внимание на теги <link>
.
И теперь я вижу, что в исходном коде вместо трёх тегов <link>
присутствует два, а ссылки в них невероятным образом изменились. Если проследовать по этим ссылкам, можно увидеть минимизированный исходных код результирующих файлов, которые сгруппированы из перечисленных в соответствующем блоке assets
соответствующего шаблона.
Делаю простой вывод: изменяя опцию ASSETS_DEBUG
разработчик получает возможность видеть исходный код на стадии разработки проекта, или минимизированный код в продакшене.
Git
На текущий момент все цели этой демонстрации полностью достигнуты, базовый шаблон свёрстан, и все необходимые блоки в нём выделены. Пришло время сделать очередной commit. Давайте взглянем на статус репозитория.
$ git status
Как видно на снимке экрана, наряду с другими изменениями, в проекте появились два каталога (.webassets-cache
и generic
), созданные в результате обработки кода инструментами библиотеки webassets, и этим каталогам не место на публичном Git-сервере, их обработку нужно исключить. Для этого открываю в текстовом редакторе файл .gitignore
.
$ vim .gitignore
И дописываю в конец файл две дополнительные строчки с относительными адресами каталогов .webassets-cache
и generic
.
Сохраняю изменения в файл и делаю очередной commit. Текущий этап разработки завершен, продолжение следует.
Продолжение следует
Как всегда, вопросы и предложения отправляйте в комментарии, синяя кнопка ниже работает, специально для застенчивых предусмотрен приват - я готов отвечать на ваши вопросы. А лайки, подписки и донаты будут для автора дополнительным стимулом продолжить это описание. Увидимся...