Написать пост

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2

Привели код для переноса данных из JSON в Django SQL, задеплоили блог на Railway + Cloudflare, научили рендерить формулы на MathJax.

Обложка поста Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2

Если вы задумываетесь над переходом на самописный сайт и понимаете основы Python, эта статья поможет узнать, как сделать блог на Django 4.

Это продолжение статьи о миграции с low-code CMS на Django. В первой части мы развернули проект с симпатичным дизайном на локальном сервере, подготовили данные для загрузки в хранилище SQL (ссылка).

Запустим сайт, что получили в первой части

При каждом запуске сервера командой:

			python manage.py runserver
		

Запуск проекта Django отправляет нас по ссылке http://127.0.0.1:8000/. Конечно, другие пользователи ее не увидят, даже если компьютер будет запущен круглосуточно. Потому настало время привязать к проекту домен.

Переносим данные

Мой сайт сидел на CMS под названием Ghost. Главным преимуществом я всегда считала возможность сменить тему без необходимости программировать и достаточно отлаженные для мобильных устройств шаблоны страниц.

Теперь, когда ценник возрос (в связи с ростом числа читателей) и отключением Visa / Mastercard на территории РФ, оплачивать подписку на эту систему стало невыгодно. Конечно, обходные пути для оплаты всегда найдутся, но умельцы навешивают комиссию в 20%. Со временем это начинает раздражать.

За «только платный» план Ghost делает свою работу очень достойно: в секции Labs блогер может скачать весь контент. Нечасто CMS настолько дружелюбны к перспективе миграции.

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 1

При скачивании получаем такой JSON-массив со статьями:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 2

Django-проект сидит на SQLite (придется пересаживать на PostgreSQL), так что придется вытащить некоторые поля и загнать их в SQL-запрос.

Чтобы залить все 246 статей в базу, нужно проитерировать файл на 6800+ строк и вытащить обязательные параметры: название поста, описание, текст с HTML-разметкой, URL картинки и slug (псевдоним статьи на латинице для формирования ссылки вида https://ww.helenkapatsa.ru/blogpost/slug).

			import json
from datetime import datetime

# Откроем выгрузку статей
with open('/Users/elenakapatsa/Repositories/django-tailwind-blog/modya-export-2023-09-27.json') as json_file:
    data = json.load(json_file)

i = 0
articles = []

# Выделим из массива параметры статьи
for i in range(len(data['db'][0]['data']['posts'])):
    sno = i + 1 # В SQL нумерацию начнем с единицы
    title = data['db'][0]['data']['posts'][i]['title'] # Заголовок
    meta = '' # Описание
    content = data['db'][0]['data']['posts'][i]['html'] # Текст статьи
    thumbnail_img = '' # Ссылка на обложку
    # Псевдоним для формирования ссылки
    slug = data['db'][0]['data']['posts'][i]['slug']
    # Выделим время написания (try - except нужен из-за пустот)
    try:
        time_obj = data['db'][0]['data']['posts'][i]['published_at']
        print(time_obj)
        date_obj = datetime.strptime(time_obj, '%Y-%m-%dT%H:%M:%S.000Z')
        time = str(date_obj.date())
    except TypeError:
        time = '2023-09-27'

    # Категория публикации
    category = ''    
    thumbnail_url = ''

    articles.append({'sno': sno, 
                     'title': title,
                     'meta': meta,
                     'content': content,
                     'thumbnail_img': thumbnail_img,
                     'slug': slug,
                     'time': time,
                     'category': category,
                     'thumbnail_url': thumbnail_url
                     })
		
Внимательные могли заметить, что при выделении параметров category, thumbnail_url остаются пустыми: в Ghost-выгрузке попросту нет аналогичных полей.

Созданный список из словарей заливаем в файл:

			# Выгрузим
final = json.dumps(articles, 
                   ensure_ascii=False,
                   indent=2)

with open('articles.json', 'w') as outfile:
    outfile.write(final)
		

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

			# -*- coding: utf-8 -*-
		

Теперь, подключив модуль sqlite3, заливаем посты:

			import json
import sqlite3

# Откроем базу
conn = sqlite3.connect("db.sqlite3")

# Исполним запрос с подстановкой полей массива
with open('/path/to/file/django-tailwind-blog/articles.json', 'r') as json_file:
    data = json.load(json_file)
    for item in data:
        conn.execute("INSERT INTO home_blog (sno, title, meta, content, thumbnail_img, slug, time, category, thumbnail_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", (item["sno"], item["title"], item["meta"], item["content"], item["thumbnail_img"], item["slug"], item["time"], item["category"], item["thumbnail_url"]))

conn.commit()
# Закроем базу
conn.close()
		

Основной объем работ по переносу выполнен, админка наводнилась постами:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 3

На сайте появились статьи, большая часть из них, к сожалению, без обложки. Придется писать скрипт, как с Unsplash, выделить картинки ссылками и обновить данные постов:

Деплоим на сервере

Первый шаг в этом процессе — развернуть репозиторий на круглосуточно работающем сервере. С этим здорово помогают сервисы вроде Railway: достаточно привязать свой GitHub-аккаунт, чтобы подтянулся нужный:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 4

После построения проекта, которое заняло около двух минут, можем посмотреть статус развертывания:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 5

Сам сайт теперь доступен и на выделенном поддомене web-production-99b09.up.railway.app. Но нас интересует – helenkapatsa.ru.

Регистратор – reg.ru, и стандартная процедура вставки CNAME-записи не сработает:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 6

Поэтому используем Cloudflare. Он предоставляет бесплатные DNS-сервера. После регистрации и ввода доменного имени получаем инструкцию:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 7

Замена ns1/2.reg.ru на адреса Cloudflare заняла менее 10 минут. Осталось добавить CNAME-запись, указывающую на Railway-приложение:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 8

Спустя примерно 10 минут сайт доступен по адресу helenkapatsa.ru:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 9

Устанавливаем плагин

Когда речь заходит о статистическом/математическом термине, зачастую к посту я прикладываю формулу. Чтобы Django рендерил MathJax (один из способов записать такое выражение), нам потребуется библиотека django-mathjax. Ее устанавливаем классической командой:

			pip3 install django-mathjax
		

Пополняем перечень требуемых инструментов (requirements.txt), чтобы Railway при редеплое прошелся по этому файлу и установил инструмент:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 10

Затем в шапку шаблона поста добавляем инструкцию, которая просит движок рендерить формулы при нахождении, как это заведено среди ученых:

/path/to/file/templates/blogpost.html:

			{% mathjax_scripts %}
		

Теперь при попадании такого синтаксиса в текст:

			$$z = \frac{x - μ}{σ}, где$$
$$z\space{-}\space{,}$$
$$x\space{-}\space{значение выборки,}$$
$$μ\space{-}\space{среднее,}$$
$$σ\space{-}\space{стандартное}\space{отклонение}$$
		

Код превратится в красоту:

Мигрируем с no-code CMS на Django: пошаговый гайд, часть 2 11

Заключение

Идеально не бывает, потому я планирую вернуть всем статьям обложки — фотографии животных с Unsplash — поэкспериментировать с диалоговым ассистентом, снова внедрить сниппет рекламной сети Яндекс и прочие улучшения.

Поддержка сайта не усложнится, пока вы регулярно практикуете Python. Такая миграция – это возможность попробовать инструменты, которые на работе внедрить не удается. Тем самым вы можете пополнять резюме до нужной комбинации технологий.

175 открытий870 показов