четверг, 20 декабря 2007 г.

Миграции в Django

В RoR имеется концепция миграций: все изменения в моделях фиксируются определённым образом, чтобы потом можно было проапдейтить и development и production БД _автоматически_.

Django не умеет синхронизировать изменения моделей с БД (по крайней мере, на момент написания этого текста) :-(

Отсюда проблема - как быть ?

Вот так - Django Evolution.

Как юзать ?

В общем-то, элементарно. Но, имеются тонкости: если у вас ещё не было _ни одного_ syncdb с моделью, то эта система не сработает. Поэтому подключить к проекту на этапе, когда нет ни одной модели (в самом начале проекта), не получится. Я об этом упоминаю отдельно, чтобы вы не наступали на ненужные грабли.

Теперь, по шагам, для нового проекта:

1) создаём какие-то модели (модель)
2) делаем manage.py syncdb
3) забираем Django Evolution из SVN: svn checkout http://django-evolution.googlecode.com/svn/trunk/ django-evolution-read-only
4) копируем подкаталог django_evolution в свой проект (или, если есть возможность, делаем симлинк)
5) в settings.py в INSTALLED_APPS добавляем django_evolution
6) делаем новый подкаталог для всех app, которые в проекте - evolutions, в нём создаём файл "__init__.py"
7) после изменений в модели делаем manage.py syncdb, видим "Project signature has changed - an evolution is required"
8) делаем manage.py evolve --hint, видим что-то вроде этого:

#----- Evolution for website
from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
DeleteField('Poll', 'pub_date')
]
#----------------------
Trial evolution successful.
Run './manage.py evolve --hint --execute' to apply evolution.

9) теперь копируем весь текст между строками с #-----, т.е. в данном случае:

from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
DeleteField('Poll', 'pub_date')
]

в файл с информативным названием(в данном случае удаляется поле pub_date в модели Poll, называем delete_poll_pub_date.py) в каталог evolutions для app, в котором изменения. У меня app называется website, поэтому получается так:

/website
/evolutions
delete_poll_pub_date.py
__init__.py
не забыли создать __init__.py до этого ?

10) теперь добавляем в файл evolutions/__init__.py такую строчку:

SEQUENCE = ['delete_poll_pub_date']

т.е., в файле evolutions/__init__.py задаётся последовательность модификаций БД.

11) пишем

manage.py evolve --execute

выводится вопрос, отвечаем yes (чтобы всё проходило без вопросов, нужно добавить к команде ключ --noinput, но лучше оставить без --noinput, чтобы было похоже на Terminator 3 :-) ).

В результате имеем: Evolution successful. Т.е. прошёл апдейт структуры БД. Если ещё раз набрать manage.py evolve --execute, выведется "No evolution required."

Вот таким образом это всё работает.

Копируем на production все изменения в нашем коде, включая все файлы evolutions, и там запускаем manage.py evolve --execute.

Конечно, это не полный автомат - но согласитесь, намного лучше, чем ничего. Я думаю, что можно усовершенствовать скрипт, чтобы он сам создавал необходимое в evolutions, но самому некогда.

Насчёт багов пока не в курсе, так что про бекапы не забываем :-)
Читаем полную доку либо тут, либо в docs, который пришёл с svn.

Успехов !

Комментариев нет:

Отправить комментарий