Каков рекомендуемый подход к сбросу истории миграции с использованием Django South?

153

Я накопил довольно много миграций, используя South (0.7) и Django (1.1.2), которые начинают занимать довольно много времени в моих модульных тестах. Я хотел бы сбросить базовый уровень и начать новый набор миграций. Я просмотрел южную документацию , выполнил обычный поиск в Google / Stackoverflow (например, «django south (сбросить или удалить или удалить) историю миграции») и не нашел ничего очевидного.

Один из подходов, который я рассмотрел, заключается в том, чтобы «начать заново», удалив «Юг» или «очистить» историю вручную (например, очистить таблицу БД, удалить файлы миграции из директора миграции) и просто запустить заново,

./manage.py schemamigration southtut - начальный

Так что, если кто-то делал это раньше и имеет несколько советов / предложений, они будут очень благодарны.

Гленн Снайдер
источник
иногда нужно вручную добавить __init__.pyвappname/migrations
laike9m
2
Как вы сбрасываете миграции в 1.7 (со встроенной миграцией)?
Тимо
1
@Timo: docs.djangoproject.com/en/dev/topics/migrations/… может быть подходом. Вы также можете просто удалить свои миграции / каталоги и переиздать, ./manage.py makemigrationsно плохие вещи произойдут, если вы не начнете с новой базы данных ...
Jocelyn delalande
Я думаю squashmigrations, что правильный ответ
Хулио Маринс

Ответы:

121

РЕДАКТИРОВАТЬ - я помещаю комментарий внизу вверху, так как важно прочитать его до> принятого ответа, следующего за @andybak

@Dominique: Ваш совет относительно manage.py reset на юг опасен и может разрушить базу данных, если в проекте есть сторонние приложения, использующие south, как указано @thnee ниже. Поскольку в вашем ответе так много откликов, я был бы очень признателен, если бы вы могли отредактировать его и добавить хотя бы предупреждение об этом или (еще лучше) изменить его, чтобы он отражал подход @hobs (что так же удобно, но не влияет на другие приложения) - спасибо! - Крив Мар 26 '13 в 9:09

Принятый ответ следует ниже:

Во-первых, ответ южного автора :

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

    rm -r appname/migrations/ 
    ./manage.py reset south 
    ./manage.py convert_to_south appname 

(Обратите внимание, что reset southчасть « » очищает записи миграции для ВСЕХ приложений, поэтому убедитесь, что вы запустили две другие строки для всех приложений или удалили их выборочно).

convert_to_southВызов в конце делает новую миграцию и поддельный применяет его (так как база данных уже имеют соответствующие таблицы). Нет необходимости отбрасывать все таблицы приложений во время процесса.

Вот что я делаю на своем рабочем сервере dev +, когда мне нужно избавиться от всех этих ненужных миграций разработчиков:

  1. Убедитесь, что у нас одинаковая схема БД с обеих сторон
  2. удалить каждую папку миграций с обеих сторон
  3. запустить ./manage.py сбросить юг (как говорится в посте) с обеих сторон = очищает южную таблицу *
  4. запустите ./manage.py convert_to_south с обеих сторон (фальшивая миграция 0001)
  5. тогда я могу перезапустить, чтобы сделать миграции и толкать папки миграций на моем сервере

* за исключением случаев, когда вы хотите очистить только одно приложение среди других, в этом случае вам нужно будет отредактировать таблицу south_history и удалить только записи о вашем приложении.

Доминик Гвардиола
источник
2
Просто запомните, что ответ южного автора был следующим: если вы позаботитесь о том, чтобы сделать это во всех развертываниях одновременно, с этим не должно быть никаких проблем. Лично я бы сделал: rm -r appname / migrations / ./manage.py сбросить юг ./manage.py convert_to_south appname (обратите внимание, что часть «сброс юга» очищает записи миграции для ВСЕХ приложений, поэтому убедитесь, что вы либо запустили две другие строки для всех приложений или выборочно удалить).
Адриан Тайсселинг
2
Также обратите внимание, что если вы отбрасываете таблицы, вам нужно manage.py schemamigration app name --initialвместо convert_to_south.
Адриан Тайсселинг
7
Начиная с Django 1.5, команда управления «сброс» пропала. Вместо этого вы захотите сделать что-то вроде south.models.MigrationHistory.objects.all().delete().
Андрей Б.
13
@Dominique: Ваш совет относительно manage.py reset southявляется опасным и может уничтожить базу данных , если есть какая - либо приложение стороннего использующего юга в проекте, как отметило @thnee ниже. Поскольку в вашем ответе так много откликов, я был бы очень признателен, если бы вы могли отредактировать его и добавить хотя бы предупреждение об этом или (еще лучше) изменить его, чтобы он отражал подход @hobs (что так же удобно, но не влияет на другие приложения) - спасибо!
Крив
3
Почему это так высоко проголосовало? Вы почти НИКОГДА не должны полностью удалять свою таблицу south_migrationhistory. Это полностью испортило бы все зависимые приложения с миграциями, которые вы не хотите трогать. Hob ответ правильный.
Cerin
188

Если вам нужно выборочно (только для одного приложения) сбросить миграцию, которая занимает слишком много времени, это сработало для меня.

rm <app-dir>/migrations/*
python manage.py schemamigration <app-name> --initial
python manage.py migrate <app-name> 0001 --fake  --delete-ghost-migrations

Не забудьте вручную восстановить любые зависимости от других приложений, добавив строки, подобные depends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial"))вашему <app-dir>/migrations/0001_initial.pyфайлу, как первый атрибут в вашем классе миграции чуть ниже class Migration(SchemaMigration):.

Вы можете затем ./manage.py migrate <app-name> --fake --delete-ghost-migrationsв других средах, согласно этому SO ответу . Конечно , если вы поддельные удаления или поддельные migrate zeroвам нужно вручную удалять левой более таблиц БД с миграцией , как это .

Более ядерный вариант заключается в ./manage.py migrate --fake --delete-ghost-migrations на сервере развертывания в реальном времени, за которым следует [my] sqldump. Затем направьте этот дамп в [my] sql в тех средах, где вам нужна перенастроенная, полностью заполненная база данных. Южная кощунство, я знаю, но работало на меня.

варочные панели
источник
2
Что я действительно хочу, так это «возьмите models.py как Евангелие и с этого момента меня очистить». Таким образом, сохраняется возможность настроить развертывание с нуля или работать с существующим развертыванием.
Брайс
1
Вот что это делает.
варенье
2
@hobs Я немного подделал DependsOnUnknownMigrationновую первоначальную миграцию. Благодаря вашему комментарию я смог выяснить, что мне следует обновлять depends_onутверждение везде, где оно относится к этому приложению. Это действительно лучший ответ здесь. Спасибо! :)
manu
55

Благодаря ответам Доминика Гвардиолы и Варвара, это помогло мне решить сложную проблему. Однако есть несколько проблем с решением, вот мое мнение о нем.

Использование manage.py reset southэто не очень хорошая идея , если у вас есть какие - либо сторонние приложения , которые используют Юг, например django-cms( в основном все использует Юг).

reset south удалит всю историю миграции для всех приложений, которые вы установили.

Теперь учтите, что вы обновляетесь до последней версии django-cms, она будет содержать новые миграции, такие как 0009_do_something.py. Юг, несомненно, будет сбит с толку, когда вы попытаетесь запустить эту миграцию, не пройдя 0001сквозь 0008историю миграции.

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


Прежде всего, убедитесь, что ваши приложения не имеют рассинхронизации между миграциями на диске и миграциями, которые были выполнены в базе данных. В противном случае будет головная боль.

1. Удалить историю миграции для моих приложений

sql> delete from south_migrationhistory where app_name = 'my_app';

2. Удалить миграции для моих приложений

$ rm -rf my_app/migrations/

3. Создайте новые начальные миграции для моих приложений

$ ./manage.py schemamigration --initial my_app

4. Поддельные выполнить начальные миграции для моих приложений

Это вставляет миграции в south_migrationhistoryбез касания реальных таблиц:

$ ./manage.py migrate --fake my_app

Шаг 3 и 4 на самом деле просто более длинный вариант manage.py convert_to_south my_app, но я предпочитаю этот дополнительный контроль в такой сложной ситуации, как изменение производственной базы данных.

thnee
источник
2
Я отредактировал свой ответ, чтобы включить исправления для найденных проблем (просто угадывая их на основе вашего ответа), и проверил его в рабочей базе данных с миллионами строк.
вар
2
Это в значительной степени то, что мы делаем. Если вы используете опцию --delete-ghost-migrations на шаге 4, вы можете пропустить шаг 1.
tobych
Вы должны явно указать имена приложений, ./manage.py migrate --fakeесли вы не хотите фальсифицировать миграцию других приложений, которые ожидают миграции.
Вадим
2
@wadim Следовательно, шаг 0: «убедитесь, что у вас нет рассинхронизации между миграциями на диске и миграциями, которые были выполнены в базе данных».
thnee
@ Правильно. Вероятно, стоит упомянуть, что вы ссылаетесь на все установленные приложения на шаге 0. Хотя вы знаете простой способ выполнить шаг 0?
Вадим
7

Как и в случае с ней (см. Ее ответ), мы используем более мягкий подход к предложению автора на юге (Эндрю Годвин), цитируемому в другом месте здесь, и мы отделяем то, что мы делаем с базой кода, от того, что мы делаем с базой данных, во время развертывания потому что нам нужно, чтобы развертывания были повторяемыми:

Что мы делаем в коде:

# Remove all the migrations from the app
$ rm -fR appname/migrations
# Make the first migration (don't touch the database)
$ ./manage.py schemamigration appname --initial

Что мы делаем с базой данных после развертывания этого кода

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations
tobych
источник
Я думаю, что я сделал то же самое, но вручную удалял записи базы данных, а не использовал --delete_ghoist-migrations. Твой путь немного приятнее.
wobbily_col
1

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

http://balzerg.blogspot.co.il/2012/09/django-app-reset-with-south.html

В отличие от предложения автора на юге, это НЕ ВРЕДИТ другим установленным приложениям, использующим юг.

idanzalz
источник
И если, в отличие от автора, вы хотите сохранить существующие миграции (т.е. вы хотите сбросить приложение, а также историю миграции, но сохранить фактические миграции), вы можете попробовать это: goo.gl/0ZnWm
mgalgs
1

Следующее только если вы хотите сбросить все приложения. Пожалуйста, сделайте резервную копию всех ваших баз данных до этой работы. Также запишите ваши зависимости в исходных файлах, если таковые имеются.

Однажды:

(1) find . -type d -name migrations -exec git rm -rf '{}' \;
(2) find . -type d -name migrations -exec rm -rf '{}' \;
(3) ./manage.py schemamigration <APP_NAME> --initial
(4) [GIT COMMIT]

Протестируйте ваш проект перед загрузкой. Затем для каждого локального / удаленного компьютера примените следующее:

(5) [GIT PULL]
(6) ./manage.py reset south
(7) ./manage.py migrate --fake

Сделайте начальный (3) для каждого приложения, которое вы хотите повторно привлечь. Обратите внимание, что reset (6) удалит только историю миграции, поэтому не будет вреден для библиотек. Ложные миграции (7) вернут историю миграции любых сторонних установленных приложений.

yasc
источник
0

удалить необходимый файл из папки приложения

путь к экземпляру

 cd /usr/local/lib/python2.7/dist-packages/wiki/south_migrations

вики-мое приложение

Андрей Еремчук
источник