Как упростить миграцию в Django 1.7?


92

Подобные вопросы уже есть для South, но я начал свой проект с Django 1.7 и не использую South.

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

Каков рекомендуемый способ сделать это?

РЕДАКТИРОВАТЬ: Начиная с Django 1.8 есть новая команда под названием squashmigrations, которая более или менее решает проблему, описанную здесь.


Что значит сбросить миграцию? Отменить?
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:


137

Я понял это. Я только что в этом разобрался, и это хорошо.

  • Во-первых, чтобы очистить таблицу миграций:

    ./manage.py migrate --fake <app-name> zero
    
  • Удалить app-name/migrations/папку или содержимое.

  • Сделайте миграции:

    ./manage.py makemigrations <app-name>
    
  • Наконец, приведите в порядок свои миграции, не внося других изменений в базу данных:

    ./manage.py migrate --fake <app-name>
    

5
Это хороший ответ. Простое удаление миграций не отменяет никакого ущерба, нанесенного ошибочными миграциями. Это фактически очищает сланец и позволяет вам начать все сначала.
rogueleaderr

15
Если вы немного уточнить, это должен быть принятый ответ.
tani-rokk

8
Отличный однострочный ответ, братан, я понятия не имею, что это делает
Бишоффингстон

13
Эта строка просто отменяет миграции одну за другой, пока zero. Для системы миграции Django <app-name> это новое приложение, которое makemigrations <app-name>будет начинаться с 0001. --fakeпредотвращает фактическое изменение таблиц, поэтому миграции должны быть помечены только как обратные, а не применяться к схеме. (Добавляем небольшие пояснения для полноты картины, @ tani-rokk, @Fabrizio)
Мир Назим

17
manage.py migrate --fake <app-name> zeroчтобы очистить таблицу миграций, затем удалите папку или содержимое <app-name> / migrations /. Тогда manage.py makemigrations <app-name>и наконец сделаю manage.py migrate --fake <app-name>. Это упорядочит ваши миграции без внесения других изменений в базу данных.
doeke

36

В версии миграций Django 1.7 функция сброса, которая раньше была в South, была удалена в пользу новой функции для «подавления» ваших миграций. Предполагается, что это хороший способ контролировать количество миграций.

https://docs.djangoproject.com/en/dev/topics/migrations/#squashing-migrations

Если вы все еще хотите начать с нуля, я предполагаю, что вы все еще можете очистить таблицу миграций и удалить миграции, после чего вы должны будете запустить ее makemigrationsснова.


2
Как мне «удалить миграции», кроме очистки таблицы миграций? Могу ли я удалить всю папку или только файлы 00X _ *. Py?
Кит Фисто

с Югом вы можете удалить папку миграции, которая будет воссоздана при повторном запуске makemigrations. Я предполагаю, что это работает так же для Django 1.7
tijs

4
Просто примечание. в Django 1.7, если вы неосторожно удалите папку миграции, это может вызвать исключение, если ваша модель является дочерней по отношению к другойraise KeyError("Migration %s dependencies reference nonexistent parent node %r" % (migration, parent))
Algorithmatic

В частности, ./manage.py squashmigrations myapp 0004будет подавлять все миграции перед миграцией 0004в вашем приложении myapp. Это создаст единую сжатую миграцию.
Брайс Гуинта,

22

У меня была такая же проблема. Вот мой способ обхода.

#!/bin/sh
echo "Starting ..."

echo ">> Deleting old migrations"
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete


# Optional
echo ">> Deleting database"
find . -name "db.sqlite3" -delete

echo ">> Running manage.py makemigrations"
python manage.py makemigrations

echo ">> Running manage.py migrate"
python manage.py migrate

echo ">> Done"

Команда find: http://unixhelp.ed.ac.uk/CGI/man-cgi?find


13
это удаляет данные, а не только миграции
hobs

2
вам также следует удалить файлы .pyc
shalbafzadeh

7

Предполагая, что это структура вашего проекта,

project_root/
    app1/
        migrations/
    app2/
        migrations/
    ...
    manage.py
    remove_migrations.py

вы можете запустить скрипт remove_migrations.py из указанного выше места, чтобы удалить все файлы миграции.

#remove_migrations.py
"""
Run this file from a Django =1.7 project root. 
Removes all migration files from all apps in a project.
""" 
from unipath import Path

this_file = Path(__file__).absolute()
current_dir = this_file.parent
dir_list = current_dir.listdir()

for paths in dir_list:
    migration_folder = paths.child('migrations')
    if migration_folder.exists():
        list_files = migration_folder.listdir()
        for files in list_files:
            split = files.components()
            if split[-1] != Path('__init__.py'):
                files.remove()

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

Однако когда я удалил папку миграции makemigrationsили migrateне создал ее для себя. Скрипт следит за тем, чтобы папка миграции __init__.pyоставалась на месте, удаляя только файлы миграции.


вы можете просто удалить папки миграции и воссоздать их с пустым init .py (например touch migrations/__init__.py)
hobs

6
  1. Удалите файлы: delete_migrations.py (в корне prj):
import os

for root, dirs, files in os.walk(".", topdown=False):
  for name in files:
      if '/migrations' in root and name != '__init__.py':
          os.remove(os.path.join(root, name))
  1. DELETE FROM django_migrations Where app in ('app1', 'app2');

  2. ./manage.py makemigrations

  3. ./manage.py migrate --fake

ИЛИ вы можете написать миграцию из всего этого


Мне пришлось указать имена приложений, ./manage.py makemigrationsчтобы они работали, например:./manage.py makemigrations orders alerts
Salami

4

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

Перед тем как это сделать, убедитесь, что база данных уже синхронизирована (например, не добавляйте здесь новое поле Model или не меняйте параметры Meta).

rm -Rf MYAPP/migrations/*
python manage.py makemigrations --empty MYAPP
python manage.py makemigrations
python manage.py migrate --fake MYAPP 0002

Где 0002 - это номер миграции, возвращенный последней командой makemigrations.

Теперь вы можете снова запустить makemigrations / migrate, поскольку миграция 0002 сохраняется, но не отражается в уже синхронизированной базе данных.


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

3

Если вас не интересуют предыдущие миграции, как насчет того, чтобы просто удалить все миграции в каталоге migrations /? вы начнете последовательность миграции с нуля, взяв текущую модель за образец, как если бы вы написали всю модель сейчас.

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


Какое значение имеет сохранение старых миграций? Мои вопросы касаются земли, когда кто-то пытается перейти с django 1.6 до 1.8.
Джей Моди

Миграции - это просто запись изменений, внесенных вами в базу данных. Я не раз прислушивался к совету вокимана, когда моя миграционная цепочка перестала работать.
Адам Старр

1

Простой способ

Перейдите в каждое приложение и удалите файлы миграции.

Затем перейдите к таблице django-migrtaions в базе данных и обрежьте ее (удалите все записи).

После этого вы можете снова создавать миграции.


1
при удалении файлов миграции убедитесь, что вы не удалили файлы инициализации .
sprksh 06

Это мне действительно помогло. Я удалил все миграции, удалил таблицы из моей базы данных sqlite, но все еще не смог выполнить миграции ... однако, как только я восстановил файлы _init_ .py (doh), я смог снова выполнить миграции и отправиться в круиз. @sprksh = Спасатель!
twknab

0

cd в каталог src cd /path/to/src

удалить каталоги миграции rm -rf your_app/migrations/

обратите внимание, что это нужно делать для каждого приложения отдельно

мигрировать python3.3 manage.py migrate

если вы хотите начать заново python3.3 manage.py makemigrations your_app


0

Если вы находитесь в режиме разработки и просто хотите сбросить все (базу данных, миграции и т. Д.), Я использую этот сценарий на основе ответа Абдельхамида Ба. Это приведет к стиранию таблиц базы данных (Postgres), удалению всех файлов миграции, повторному запуску миграции и загрузке моих исходных фикстур:

#!/usr/bin/env bash
echo "This will wipe out the database, delete migration files, make and apply migrations and load the intial fixtures."

while true; do
    read -p "Do you wish to continue?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo ">> Deleting old migrations"
find ../../src -path "*/migrations/*.py" -not -name "__init__.py" -delete

# Optional
echo ">> Deleting database"
psql -U db_user -d db_name -a -f ./reset-db.sql

echo ">> Running manage.py makemigrations and migrate"
./migrations.sh

echo ">> Loading initial fixtures"
./load_initial_fixtures.sh

echo ">> Done"

файл reset-db.sql:

DO $$ DECLARE
    r RECORD;
BEGIN
    -- if the schema you operate on is not "current", you will want to
    -- replace current_schema() in query with 'schematodeletetablesfrom'
    -- *and* update the generate 'DROP...' accordingly.
    FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
        EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
    END LOOP;
END $$;

Файл migration.sh:

#!/usr/bin/env bash
cd ../../src
./manage.py makemigrations
./manage.py migrate

load_initial_fixtures.sh файл:

#!/usr/bin/env bash
cd ../../src
./manage.py loaddata ~/path-to-fixture/fixture.json

Только не забудьте изменить пути, соответствующие вашему приложению. Лично у меня эти скрипты находятся в папке с именем project_root / script / local, а исходные коды django находятся в project_root / src.


0

После удаления каждой папки «миграции» в моем приложении (вручную) я запустил:

./manage.py dbshell
delete from django_migrations;

Тогда я подумал, что могу просто ./manage.py makemigrationsвосстановить их всех. Однако никаких изменений не обнаружено. Затем я попытался указать одно приложение за раз: ./manage.py makemigrations foo, ./manage.py makemigrations bar. Однако это привело к циклическим зависимостям, которые не удалось устранить.

Наконец, я выполнил одну команду makemigrations, в которой были указаны ВСЕ мои приложения (без определенного порядка):

./manage.py makemigrations foo bar bike orange banana etc

На этот раз это сработало - циклические зависимости были автоматически разрешены (при необходимости были созданы дополнительные файлы миграции).

Затем я смог бежать ./manage.py migrate --fakeи вернулся в бизнес.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.