Стартовая страница web-приложения на Python и Starlette
programming
Стартовая страница web-приложения на Python и Starlette, разработку которого мы исследуем в этом цикле статей, в жизненном цикле web-сайта может иметь разные редакции. Иногда сайт разворачивают на конкретном домене задолго до готовности всего задуманного web-мастером функционала, и в этом случае стартовая страница должна быть свёрстана в первую очередь. В этом выпуске блога я покажу вёрстку только первой редакции стартовой страницы, впоследствии к этой теме так или иначе придётся вернуться ещё раз.
Базовый шаблон
Начинать вёрстку стартовой страницы я буду с доработки базового шаблона, я предупреждал ранее, что к нему мы будем возвращаться много раз снова и снова. Открываю файл в текстовом редакторе Vim, параллельно в соседнем терминале запускаю отладочный сервер, запускаю браузер и стучусь по соответствующему url-адресу.
$ vim webapp/templates/base.html
На текущий момент заголовок страницы в теге <head>
базового шаблона задан простой константой. Мне бы хотелось в этот заголовок подтягивать имя сайта из файла настроек, более того, заголовок хочется дифференцировать для каждой страницы сайта соответствующим этой странице образом. Нахожу в базовом шаблоне блок с именем title
и редактирую его содержимое следующим образом.
{% block title %}
<title>
{{ config.get('SNAME') }}:
{% block title_part %}{% endblock title_part %}
</title>
{% endblock title %}
В этом коде я задал имя сайта и создал ещё один блок с именем title_part
внутри блока title
.
Двигаюсь по коду базового шаблона вниз, в теге <body>
нахожу комментарий между тегами <nav>
и <footer>
, заботливо оставленный мной на предыдущем этапе разработки. Под этот комментарий определяю тег <div>
с идентификатором page-content
и в нём задаю ещё один блок — блок с именем page_body
.
<div id="page-content">
<div id="mc">
{% block page_body %}{% endblock page_body %}
</div>
</div>
Вот как этот код выглядит в окне моего текстового редактора.
Имея определённые в базовом шаблоне блоки и зная их имена, я с лёгкостью могу манипулировать ими в любом другом шаблоне, который наследует от базового шаблона.
Вёрстка стартовой страницы
В окне текстового редактора, в его командном режиме открываю файл стартовой страницы web-приложения.
:edit webapp/templates/main/index.html
Дописываю в код этого шаблона блок с именем title_part
.
{% block title_part %}
Index Page
{% endblock title_part %}
Стартовая страница web-сайта индексируется поисковыми роботами, хорошим тоном будет представить на стартовой странице краткое описание всего сайта. Мне понадобится ещё один тег <meta>
. Добавляю в шаблон блок с именем metas
.
{% block metas %}
{{ super() }}
<meta name="description"
content="{{ config.get('SDESC') }}">
{% endblock metas %}
Внутри блока я использовал вызов функции super
, это значит, что в стартовую страницу будут включены все теги одноимённого блока базового шаблона. Описание web-сайта для поисковых систем обычно должно умещаться в 160 символов. Как видно из кода, текст для этого тега я беру из файла настроек.
Открываю в окне текстового редактора файл настроек.
:split .env
Дописываю в самый конец этого файла ещё одно поле.
SDESC='Демонстрационное web-приложение на Python и Starlette'
Именно это поле я использовал в теге <meta>
. Каждую правку файла настроек необходимо сопровождать копированием файла в шаблон файла настроек, чтобы изменения отразились в Git. В командном режиме Vim эта операция может быть выполнена такой командой.
:!cp .env env_template
Возвращаюсь в окне текстового редактора к шаблону стартовой страницы и дописываю в этот шаблон новый блок — блок с именем page_body
.
{% block page_body %}
<div class="flashed-alert">
<div class="today-field"></div>
<div class="empty-message">
Сайт в стадии разработки, попробуйте зайти позже.
</div>
</div>
{% endblock page_body %}
Таким образом, в разметке стартовой страницы на данный момент я имею следующие теги <div>
:
-
<div id="page-content">
; -
<div class="flashed-alert">
; -
<div class="empty-message">
; -
<div class="today-field">
.
Каждый из этих идентификаторов будет использоваться на нескольких страницах будущего сайта, но не на всех. Вполне разумно выделить для каждого из них собственный файл с таблицами стилей. Создаю три новых файла в соответствующем каталоге и с соответствующим именем. Сделать это можно в командном режиме редактора Vim, выполняю последовательно следующие команды.
:!touch webapp/static/css/page-content.css
:!touch webapp/static/css/flashed-alert.css
:!touch webapp/static/css/empty-message.css
:!touch webapp/static/css/today-field.css
В шаблоне стартовой страницы (файл index.html
) нахожу блок с именем styles
и редактирую его, добавляю в список обрабатываемых в блоке assets
файлов имена всех только что созданных .css
файлов.
{% block styles %}
{{ super() }}
{% assets filters='cssmin', output='generic/css/main/index.css',
'css/base.css',
'css/page-content.css',
'css/flashed-alert.css',
'css/empty-message.css',
'css/today-field.css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
{% endblock styles %}
Сохраняю изменения всех файлов. Следую в окно браузера и в нём пытаюсь обновить стартовую страницу. Если при этом в окне терминала, где работает отладочный сервер, не высыпало ошибок исполнения, значит всё идёт по плану, трюк сработал, и я могу приступить к стилизации выбранных элементов DOM с одновременным тестированием страницы в браузере. Начнём с page-content
. Открываю файл с этим именем в текстовом редакторе.
:tabnew webapp/static/css/page-content.css
Вот такой код пишу в этот файл.
#page-content {
padding: 4px 0 6px;
margin-left: auto;
margin-right: auto;
width: 600px;
}
Сохраняю изменения в файл, в окне браузера обновляю страницу, полезно увидеть, как после этого редактирования изменился внешний вид страницы.
Открываю в текстовом редакторе следующий файл.
:edit webapp/static/css/flashed-alert.css
Для этого файла мне понадобится следующий код.
.flashed-alert {
border: 1px solid palegoldenrod;
border-radius: 4px;
padding: 12px;
background-color: lemonchiffon;
background-image: linear-gradient(to bottom, lemonchiffon, lemonchiffon);
box-shadow: 0 0 4px silver;
text-shadow: 0 0 4px silver;
text-align: justify;
color: gray;
margin: 0 0 4px
}
.closeable:hover {
cursor: pointer;
}
Вообще-то flashed-alert
— это имя блока для сообщений между запросами, таких сообщений пока не существует. Но на начальной стадии работы будущего сайта я буду использовать аналогичный элемент на стартовой странице. В её текущем состоянии класса closeable
не существует, это задел на будущее...
Открываю в текстовом редакторе следующий файл.
:edit webapp/static/css/empty-message.css
Для него такой код.
.empty-message {
font-style: italic;
}
Открываю в текстовом редакторе следующий файл.
:edit webapp/static/css/today-field.css
В этот файл вписываю следующий код.
.today-field {
font-style: italic;
font-size: 0.9em;
font-weight: 600;
}
Сохраняю все изменения в файлы. Перемещаюсь в окно браузера и обновляю страницу, и вот как она выглядит после всех правок кода на моём рабочем столе.
На снимке экрана выше обращаю внимание, что заголовок страницы и тег <meta>
с описанием отображаются в полном соответствии с замыслом разработчика. Что меня не устраивает? Первое, ширина блока с информационным сообщением на странице задана константой и не изменяется при изменении ширины окна браузера. Второе, в блоке информационного сообщения есть только текст сообщения, а по замыслу разработчика там должна быть ещё и текущая дата с тикающими часами.
Frontend программирование
Начнём исправлять недостатки отображения страницы с текущей даты. Поможет решить эту задачу встроенный в браузер интерпретатор JavaScript и самая капелька несложной повседневной магии.
Создаю в текстовом редакторе, в его командном режиме новый файл с именем render-tf.js
.
:edit webapp/static/js/render-tf.js
В данном случае tf
в имени файла, это сокращение от английского today field, именно так я обозначил класс соответствующего тега <div>
, осмысленные имена переменных в коде и файлов сильно облегчают жизнь разработчику и сопровождающим код впоследствии.
Пишу в этот файл следующий код.
function showDateTime(dto) {
return dto.setLocale('ru').toLocaleString(luxon.DateTime.DATE_FULL) + ', ' +
dto.setLocale('ru').toLocaleString(luxon.DateTime.TIME_WITH_SECONDS);
}
function renderTF(cls, dto) {
$(cls).text(showDateTime(dto));
setInterval(function() {
let ndto = luxon.DateTime.now();
$(cls).each(function() {
$(this).text(showDateTime(ndto));
});
}, 1000);
}
Здесь всё просто... Функция showDateTime
с помощью библиотечных объектов luxon формирует строку для отображения даты и времени. Вторая функция, её можно считать целевой, — renderTF
, с помощью инструментов jquery вставляет сформированную первой функцией строку в текст заданного с помощью параметра cls
элемента DOM. А далее функция стандартной библиотеки JavaScript setInterval
обновляет текст этого элемента DOM каждую секунду, создавая при этом эффект тикающих часов.
Чтобы трюк сработал, в файле шаблона index.html
дописываю имя только что созданного файла в список имён соответствующего assets
соответствующего блока. Вот как это выглядит в моём тестовом редакторе.
На данный момент в этом assets
присутствует ещё и файл index.js
, и чтобы часики на странице затикали, этот файл нужно определённым образом отредактировать. Открываю его в окне текстового редактора.
:split webapp/static/js/main/index.js
Весь код, который присутствовал в этом файле до этого удаляю. И пишу в этот файл новый, совсем несложный код.
$(function() {
"use strict";
let dt = luxon.DateTime.now();
if ($('.today-field').length) renderTF('.today-field', dt);
});
Здесь тоже всё элементарно. С помощью объекта jquery создаю исполняемую функцию. В теле этой функции с помощью luxon создаю объект с именем dt
(сокращение от datetime). С помощью инструментов jquery проверяю наличие в DOM элемента с классом today-field
, и если такой элемент на странице имеется, обрабатываю этот элемент с помощью только что созданной функции renderTF
.
Сохраняю все изменения в файлы. Перемещаюсь в окно браузера и в очередной раз обновляю страницу.
Снимком экрана невозможно продемонстрировать эффект тикающих часов, но поверьте мне на слово, эти часы тикают, или проверьте сами.
Теперь давайте научим программу изменять ширину блока на странице в зависимости от ширины окна браузера. Создаю в текстовом редакторе ещё один файл. Проверять я буду ширину блока с идентификатором page-content
, отсюда вытекает имя файла с программой.
:edit webapp/static/js/check-pc.js
В этом файле я создам опять две функции, одна из них будет вспомогательной, вторая целевой. Вот код.
function resize(wwidth, width) {
if (wwidth > width) {
$('#page-content').css({"width": width - 20});
} else {
$('#page-content').css({"width": wwidth - 20});
}
}
function checkPC(width) {
let wwidth = $(window).width();
let mcon = $('#page-content');
resize(wwidth, width);
$(window).on('resize', function() {
let wwidth = $(window).width();
resize(wwidth, width);
});
}
Первая функция изменяет ширину заданного блока. А вторая (checkPC
) изменяет ширину заданного блока вызовом первой функции при загрузке страницы и при изменении ширины окна браузера. Обращаю ваше внимание на имя второй функции и на то, как оно сочетается с именем файла, в котором размещена. Опять же, чтобы трюк сработал, имя только что созданного файла нужно поместить в список файлов соответствующего assets
соответствующего блока в шаблоне index.html
. Вот как это выглядит в окне моего текстового редактора.
После этого помещаю вызов функции checkPC
с желаемым параметром в теле функции в файле index.js
.
Сохраняю изменения всех файлов. Перехожу в окно браузера, обновляю страницу, а затем берусь за боковой край окна браузера и начинаю его таскать по экрану, делая окно браузера заведомо шире 860 пикселей, или заведомо уже этой величины. Вот как меняется ширина блока с информационным сообщением при этом.
Обращаю внимание, что на всех снимках экрана в консоли JavaScript инструментов разработчика браузера отсутствует выхлоп с отчётами об ошибках. Все трюки сработали.
Фиксируем транзакцию в Git
Все поставленные для этого этапа разработки цели успешно достигнуты, задачи решены, стартовая страница сайта получила свою первую, но не окончательную версию. Теперь можно добавить все изменения в Git, просмотреть их ещё раз с помощью инструментов Git и, наконец, сделать очередной commit. Код приложения в текущей редакции можно увидеть по этой ссылке.
Подводим промежуточный итог
Все цели очередного этапа разработки web-приложения достигнуты, у нас появилась более или менее информативная стартовая страница с элементами оформления, а у приложения в целом появился frontend. В одном из ближайших выпусков этого блога я научу эту программу правильно и корректно обрабатывать ошибки пользователей будущего сайта, и после этого можно будет предпринять первую попытку развернуть приложение на сервер сети на конкретном домене, чтобы поисковые роботы привыкали к домену, а у домена формировался возраст. Возраст для web-сайта штука полезная, поисковики любят долгоиграющие сайты.
Напоминаю, что продолжение этого цикла статей возможно только при наличии в блоге активности. Ваши посещения, подписки, лайки, комментарии и донаты имеют большое значение. Не оставайтесь в стороне, будет интересно...