@dibrovsd

Как в Django реализовать синхронизацию данных моделей?

Добрый день.

Есть тестовая версия приложения.
Некоторые настройки работы расположены в моделях и в код их выносить не получается,
потому что нужно настраивать через админку.

Вопрос: Как переносить данные на боевой сервер?
- Через дампы sql долго и сложно с зависимостями (нужно перенести только настройки, а документы должны остаться на месте, то есть удалить_все--вставить_все не очень подойдет)
- Использовать выгрузку и загрузку fixtures не хватает оперативной памяти (в настройках данных много, это много-проектные документообороты с более чем 5 млн. документов и полей, ролей, этапов, прав доступа там очень много)

Есть идеи по добавлению поля типа auto_now=True и выгружать diff's с даты предыдущей миграции, паковать их в файлы типа json (как fixtures) и при накате создвать файлы отката (содержащие такие же diff's, но с теми данными, которые были до применения изменений).
Последовательный накат нескольких таких файлов приведет к склейке версий.
Но это пока только абстрактная идея для своего велосипеда, который не очень хочется писать.

Мы как-то пока обходились на уровне базы данных костыльными процедурами на уровне database link,
но если тестовая база и боевая очень далеко друг от друга (тестовая на хостинге, боевая внутри локальной сети и закрыта извне), да и костыли при еженедельных релизах утомляют.

Наверняка, я не первый, кто с этим сталкивается.
Решал ли кто-то подобную задачу и как?
  • Вопрос задан
  • 2904 просмотра
Решения вопроса 1
@dibrovsd Автор вопроса
Решение для создания инкрементных данных для передачи на боевой сервер и наката их там.
На нужные модели вешаем сигналы post_delete для сохранения модель - id в модель удаленных объектов.

Привожу код создания файлов.
Чуть позже тут размещу ссылку на статью с более подробным описанием:
- Создания файлов изменений
- Накате с созданием файлов отката
- Откате изменений

# coding=utf-8

from datetime import datetime
from os import makedirs, listdir
import json

from django.core import serializers
from django.core.management.base import BaseCommand
from optparse import make_option
from django.db.models.loading import get_model
from django.conf import settings


class Command(BaseCommand):
    help = """
    Create difsettings from timestamp. 
    Usage: manage.py docflow_diffsettings_create '2014-01-01'
    """

    option_list = BaseCommand.option_list + (
        make_option('--from',
            action="store", 
            type="string",
            dest='from',
            help='timestamp: changed from argument to current DateTime'),
        make_option('--project_id',
            action="store", 
            type="int",
            dest='project_id',
            help='Docflow project number'),
    )

    def __init__(self, *vargs, **kwargs):

        super(Command, self).__init__(*vargs, **kwargs)
        self._datetime_format = '%Y-%m-%d %H:%M'

    def handle(self, *args, **options):

        date_to = datetime.now()
        date_from = datetime.strptime(options['from'], self._datetime_format)

        project_id = options["project_id"]
        project_folder = "%s/docflow/diffsettings/%s" % (settings.BASE_DIR, project_id,)
        folder_path = "%s/%s > %s" % (project_folder, 
                                    date_from.strftime(self._datetime_format),
                                    date_to.strftime(self._datetime_format))
        
        makedirs(folder_path)

        JSONSerializer = serializers.get_serializer("json")
        json_serializer = JSONSerializer()

        models_paths = set()

        for model_path in args:
            models_paths.add(model_path)

        # deleted objects
        models_paths.add('docflow.ObjectsDeleted')

        # create files
        for model_path in models_paths:

            application_name, model_name = model_path.split('.')
            model = get_model(application_name, model_name)
            objects_changed = model.objects.filter(d_change__range=(date_from, 
                                                                    date_to))
            
            # Обязательно наличие файла, даже если нет ни одной измененной модели
            # это необходимо для создания бэкапа при накате настроек 
            # (если по модели нет изменившихся, но есть удаленные объекты)
            # Создание файла отката настроек происходит 
            # внутри итерации перебота этих файлов
            with open("%s/%s.json" % (folder_path, model_path), "w") as out:
                json_serializer.serialize(objects_changed, stream=out, indent=4)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
webus
@webus
Golang | Python | NodeJS | Java
Т.е. нужно синхронизировать новую версию настроек приложения со старой в production ? Да, South тут вам не поможет) Сделайте manage команду типа update_settings, в которой проверяйте соответствие данных в моделях и добавляйте изменения.
Ответ написан
Комментировать
@dibrovsd Автор вопроса
Вроде как задача должна быть типичной:
есть test, есть production, нужно с теста сливать настройки в prod.
Неужели нет подобного механизма, доступного и поддерживаемого кем-то.

Собственно, в этом направлении и думаю.
Если никто не подскажет готового решения, так и сделаю.
Спасибо.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы