🐍😺🐙 Как сделать блог разработчика на GitHub Pages с помощью Django
Расскажем, как превратить Django в генератор статических сайтов и сделать полноценный блог с пагинацией, сортировкой записей по тегам, подсветкой синтаксиса кода, контактной формой, подпиской на рассылку и поддержкой 20 различных тем оформления.
Обзор проекта
Это генератор статических сайтов (SSG) на Django, который использует базу данных (а не Markdown файлы) для интеграции контента в HTML/CSS/JS страницы. Результат работы генератора – полностью статический блог, который с виду работает как динамический: смена темы оформления выполняются с помощью JavaScript, а обработка форм для отправки сообщения и подписки на рассылку реализована с использованием стороннего сервиса Formspree. Такой блог можно разместить на абсолютно любом статическом хостинге, включая GitHub Pages.
Демо-версию блога можно посмотреть здесь, а код доступен в репозитории django-ssg.
Особенности GitHub Pages
GitHub Pages – статический хостинг: использовать бэкенд-логику и базы данных там нельзя. В качестве бэкенда на этой платформе по умолчанию используется SSG (генератор статических сайтов) Jekyll. Он поддерживает ограниченное количество тем, а поскольку набор допустимых плагинов тоже ограничен, кастомизация и расширение функциональности Jekyll-сайтов представляют собой серьезную задачу. Существует только одно решение этой проблемы: загружать на хостинг уже готовые HTML/CSS/JS страницы.
Генерировать такие страницы можно с помощью абсолютно любого SSG – их число растет в геометрической прогрессии, есть из чего выбрать. Однако зачастую сделать собственный генератор бывает гораздо проще, чем разбираться в настройках готового SSG. Разработка генератора – несложный и увлекательный процесс: мы уже публиковали туториал о создании SSG на основе Flask и плагина Frozen-Flask. Как и абсолютное большинство других генераторов, он создает статические страницы, используя HTML/CSS/JS шаблоны и контент из файлов Markdown.
Если же вы привыкли к Django, и вместо возни с Markdown предпочитаете экспортировать записи из базы данных, для создания SSG можно воспользоваться расширением django-distill.
Как работает django-distill
Расширение django-distill выгодно отличается от других SSG-плагинов для Django (например, django-bakery) предельной простотой использования и высокой скоростью обработки файлов. Изменения в динамическую версию приложения вносятся только в одном месте – urls.py, обычные маршруты path
заменяются «дистиллированными». Например, достаточно заменить стандартный маршрут index
на этот, и расширение сгенерирует статический файл index.html:
А для экспорта всего приложения в статическую версию нужно всего лишь выполнить команду:
Ограничения django-distill
Плагин не обрабатывает URL, в которых содержатся запросы и параметры:
По этой причине django-distill не будет обрабатывать динамическую пагинацию: он экспортирует лишь первую страницу index.html, но не последующие. Хотя разработчики плагина не предлагают решение этой проблемы, оно существует – рассмотрим его ниже.
Как сделать статический сайт из приложения Django
Начнем работу с создания и активации виртуального окружения:
Перейдите в директорию проекта и активируйте окружение:
Установите Django, а затем django-distill:
Создайте новый проект:
И приложение blog:
Настройки проекта
В файле settings.py нужно сделать следующие настройки:
- Добавить django-distill и blog в раздел INSTALLED_APPS:
- Изменить язык на русский, а время – на нужный часовой пояс:
- Прописать пути к статическим и медийным файлам:
В urls.py проекта нужно добавить маршруты блога и обработку путей к статическим файлам и изображениям:
Разработка блога
Прежде всего нужно создать базу данных с помощью команды:
На этом же этапе стоит создать админский аккаунт:
После этого можно переходить к созданию схемы базы. Создайте модели Post и Tag в файле models.py:
Подготовьте и примените миграции:
Готовую заполненную базу данных можно взять в репозитории проекта.
Представления
Представления находятся в файле views.py:
- IndexView(ListView) выводит записи на главную страницу и обеспечивает пагинацию (по шесть постов для каждой страницы):
- PostView(DetailView) показывает отдельные записи и предоставляет ссылки на предыдущий и последующий посты (если они существуют):
- TagView(ListView) обеспечивает выборку постов, отмеченных определенным тегом. Эти записи также разбиваются пагинатором по 6 постов на страницу:
- Страница с контактной формой не использует серверную логику Django, поэтому шаблонизатор собирает ее из двух шаблонов и выводит без каких-либо манипуляций:
Шаблоны
Проект использует несколько шаблонов. Основные шаблоны:
Частичные шаблоны используются для включения боковой панели, пагинации и т.п. в основные шаблоны:
Все нужны скрипты находятся в статической директории и подключаются в шаблоне base.html.
Генерация статических страниц
В отличие от стандартного динамического приложения Django, вся логика генератора сосредоточена не в views.py, а в urls.py. Использование distill_path
вместо обычного path
дает плагину django-distill понять, что все страницы, соответствующие этому маршруту, нужно экспортировать в виде HTML/CSS/JS файлов. Если distill_path
нужно сгенерировать множество страниц по одному и тому же шаблону – например, страницы всех записей в хронологическом порядке или по определенному тегу, – то для получения всех слагов и всех тегов он использует соответствующие функции:
И напротив, генератор создает index.html и contact.html в единственных экземплярах, поэтому получение дополнительных данных из функций им не требуется:
Обработка пагинации
Упомянутая выше проблема с обработкой стандартной динамической пагинации решается с помощью этой функции:
И этого маршрута:
Кроме того, статическая пагинация требует специфической реализации в шаблоне _pagination.html. Этот код обеспечивает вывод страницы index.html при нажатии на первую кнопку пагинации. Все остальные страницы будут выводиться как page2.html, page3.html и так далее:
Обработка форм
Статический сайт без серверной логики не может обрабатывать пользовательский ввод (контактные формы и комментарии). Но решить эту проблему можно с использованием подходящего стороннего сервиса. Для обработки форм, например, оптимален Formspree и подобные ему сервисы. После регистрации в сервисе можно создать любую форму и получить код для ее обработки, который нужно вставить в action
:
Другие сервисы, похожие на Formspree: Formspark, Formcarry, Getform, FormKeep, FormBackend.
Подсветка синтаксиса
Для подсветки кода блог использует библиотеку highlight.js, которая поддерживает 192+ языков и 498 тем. В этом проекте используется тема Dracula, выбрать другую тему можно в разделе Examples библиотеки highlight.js.
Экспорт статических страниц из приложения Django
Когда ваш сайт полностью готов к загрузке на хостинг, нужно выполнить упомянутую выше команду:
После чего django-distill экспортирует HTML/CSS/JS страницы в директорию mysite. Перед загрузкой на хостинг стоит убедиться, что статическая версия сайта функционирует корректно. Для этого нужно вызвать cmd в директории сайта и выполнить команду для запуска локального сервера:
После этого статическую версию сайта можно будет открыть в браузере по адресу http://localhost:8000/.
Нюансы хостинга GitHub Pages
GitHub Pages разрешает создать 1 сайт с адресом username.github.io и сколько угодно сайтов типа username.github.io/repo-name. Чтобы GitHub Pages начал раздавать статические файлы из репозитория, нужно этот репозиторий настроить следующим образом:
- Перейдите в раздел Settings в репозитории, в котором находятся файлы сайта, и выберите Pages.
- На странице Pages выберите нужную ветку – скорее всего это будет main, – и нажмите Save:
Все! Через несколько секунд сайт начнет работать.
Если что-то не получилось, пишите в комментариях – поможем!
🐍 Python: от новичка до Junior за 32 урока
Ключевые моменты курса по Python, который действительно заслуживает внимания:
- 4 практических проекта для портфолио: от парсера до Telegram-бота
- Преподают специалисты из Мегафона с опытом в ML и NLP
- 90+ часов теории и практики с доступом навсегда
- Обучение можно совмещать с работой
Особенно впечатляет программа по алгоритмам и структурам данных в бонусном модуле — редко встретишь такую глубину на базовом курсе.