Часто спрашивают, как отслеживать изменение структуры сайта на Django-CMS в системах контроля версий.
В чём, собственно, проблема?
Бывает, заказчик ставит задачу разработчикам так:
- Добавить страницу «О компании» по адресу
/about/
; - Разместить на странице текст «мы самые крутые».
Как такое рекомендуется делать в Django-CMS:
- Через админку создать страницу;
- в интерфейсе редактирования структуры разместить плагин
TextPlugin
в соответствующий placeholder; - в интерфейсе редактирования контента добавить текст в этот плагин.
Все эти действия приводят к изменениям в БД, но ни один файл при этом не затронут. Соответственно, страница добавлена, а в коммит добавлять нечего. Каждый разработчик должен у себя самостоятельно создать новую страницу, а на тестовом сервере и в продакшне ещё отдельно сделать то же самое? Но это же не наш метод!
И что же делать?
На помощь нам приходят миграции данных и cms.api. Миграции данных позволяют управлять контентом в БД. Cms.api позволяет выполнять действия по управлению контентом.
Итак, создаём пустую миграцию:
python manage.py makemigrations app_name --empty
В свежесозданном файле миграции определяем функцию, которая сделает всю работу по созданию новых сущностей:
from cms.api import create_page, add_plugin, publish_page
from django.contrib.auth.models import User
def add_pages(apps, schema_editor):
page = create_page(
'about',
'default.html',
'ru'
)
placeholder = page.placeholders.get(slot='content')
add_plugin(placeholder, 'TextPlugin', 'ru', body='Мы самые крутые')
try:
user = User.objects.filter(is_superuser=True).first()
publish_page(page, user, 'ru')
except User.DoesNotExists:
print("стоит создать суперюзера, иначе опубликовать страницу можно будет только из админки, для чего всё равно нужен суперюзер")
- функция create_page создаёт страницу с заданными параметрами. Подробнее в документации;
- предположим, в шаблоне
default.html
размещён тэг{% placeholder "content" %}
. Тогда можно методомpage.placeholders.get(slot='content')
выбрать именно это место размещения для плагина; - функция
publish_page
опубликовывает отредактированную страницу. Один из обязательных параметров — пользователь, от имени которого изменённая страница публикуется. Обойти это можно, но придётся функцию переписывать. Мы же делаем как проще.
Теперь в классе миграции можно определять действия: class Migration(migrations.Migration):
operations = [
migrations.RunPython(add_pages) # это имя вышеопределённой функции
]
Применяем эту миграцию, и видим новую уже опубликованную страницу, на которой размещён текстовый плагин, и в нём набран нужный текст.
А вот миграцию уже можно определить в коммит. Что и требовалось.