Як спростити міграцію в Django 1.7?


92

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

Під час розробки було створено багато міграцій, проте програмне забезпечення ще не розроблено, і не існує бази даних, яку потрібно перенести. Тому я хотів би скинути міграції так, ніби моєю поточною моделлю була оригінальна, і відтворити всі бази даних.

Який рекомендований спосіб зробити це?

EDIT: Станом на Django 1.8 є нова команда з назвою squashmigrations, яка більш-менш вирішує проблему, описану тут.


Що означає скидання міграції? Скасувати?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Відповіді:


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
Чудова відповідь в один рядок, брате, я навіть не уявляю, що це робить
bischoffingston

13
Цей рядок просто повертає міграції по черзі, доки zero. Для системи міграції Django <app-name> тепер це новий додаток, makemigrations <app-name>який почнеться з 0001. --fakeзапобігає фактичному зміненню таблиць, що міграції повинні бути лише позначені зворотними, а не фактично застосовуватися до схеми. (Додавання невеликих пояснень задля повноти, @ tani-rokk, @Fabrizio)
Mir Nazim

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 функцію скидання, яка раніше була в Південній Європі, було вилучено на користь нової функціональності для "здушення" ваших міграцій. Це має бути хорошим способом контролювати кількість міграцій.

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

Якщо ви все-таки хочете почати все з нуля, я припускаю, що ви все-таки змогли, очистивши таблицю міграцій та видаливши міграції, після чого ви б запустили makemigrationsзнову.


2
Як би я "видалив міграції", окрім очищення таблиці міграцій? Я б видалив всю папку або лише файли 00X _ *. Py?
Кіт Фісто

з South ви можете видалити папку міграцій, яка буде відтворена при повторному запуску makemigrations. Я припускаю, що це працює однаково для Django 1.7
tijs

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

Зокрема ./manage.py squashmigrations myapp 0004, 0004у вашій програмі буде зменшено всі міграції перед міграцією myapp. Це створить єдину стиснуту міграцію.
Bryce Guinta

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
це видаляє дані, а не лише міграції
конфорки

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)
плити

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
Саламі

4

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

Перш ніж це зробити, переконайтеся, що база даних уже синхронізована (наприклад, не додайте сюди нове поле Модель або не змінюйте параметри Мета).

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 зберігається, але не відображається у вже синхронізованій базі даних.


З усіх вищезгаданих рішень лише це працювало для мене без збоїв та без видалення бази даних.
Vivek Jha

3

Якщо вас не хвилює попередня міграція, як бути з простим видаленням усіх міграцій у каталозі migrations /? Ви почнете послідовність міграції з нуля, взявши свою поточну модель як еталон, ніби ви написали всю модель зараз.

Якщо ви не довіряєте мені, що хочете видалити, спробуйте замість цього відсунути їх.


Яке значення збереження старих міграцій? Мої запитання потрапляють на землю, коли намагаються оновити з django 1.6 до 1.8.
Джей Моді,

Міграції - це просто послужний список змін, внесених до бази даних. Я неодноразово користувався порадами вокімана, коли міграційний ланцюг перестає працювати.
Адам Старр,

1

Це простий спосіб

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

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

Після цього ви можете ще раз створити міграції.


1
видаляючи файли міграції, переконайтесь, що ви не видаляєте файли init .
sprksh

Це мені справді допомогло. Я видалив усі міграції, скинув таблиці зі своєї sqlite DB, але все ще не міг робити makemigrations ... однак, як тільки я відновив файли _init_ .py (doh), я зміг знову зробити makemigrations і отримати круїз. @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 $$;

Файл migracija.sh:

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

файл load_initial_fixture.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.