Я зробив міграцію, яка додала нову таблицю і хочу повернути її та видалити міграцію, не створюючи нової міграції.
Як це зробити? Чи є команда повернути останню міграцію, і тоді я можу просто видалити файл міграції?
Я зробив міграцію, яка додала нову таблицю і хочу повернути її та видалити міграцію, не створюючи нової міграції.
Як це зробити? Чи є команда повернути останню міграцію, і тоді я можу просто видалити файл міграції?
Відповіді:
Ви можете повернутись, перейшовши на попередню міграцію.
Наприклад, якщо ваші останні дві міграції:
0010_previous_migration
0011_migration_to_revert
Тоді ви зробите:
./manage.py migrate my_app 0010_previous_migration
Потім можна видалити міграцію 0011_migration_to_revert
.
Якщо ви використовуєте Django 1.8+, ви можете показати назви всіх міграцій
./manage.py showmigrations my_app
Щоб скасувати всі міграції програми, можна запустити:
./manage.py migrate my_app zero
'0010_previous_migration'
, я не знаю, чому ви б бачили таку поведінку.
Відповідь Alasdair висвітлює основи
./manage.py showmigrations
migrate
використовуючи ім’я програми та ім’я міграціїАле слід зазначити, що не всі міграції можна змінити. Це трапляється, якщо у Джанго немає правила робити реверс. Для більшості змін, до яких ви автоматично здійснили міграцію ./manage.py makemigrations
, можливе відновлення. Однак користувацькі сценарії повинні писати як прямий, так і зворотний, як описано в прикладі тут:
https://docs.djangoproject.com/en/1.9/ref/migration-operations/
Якщо у вас була RunPython
операція, можливо, ви просто хочете відмовитись від міграції без написання логічно суворого сценарію розвороту. Наступний швидкий злом на прикладі з Документів (вище посилання) дозволяє це, залишаючи базу даних у такому ж стані, як це було після застосування міграції, навіть після її відміни.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def forwards_func(apps, schema_editor):
# We get the model from the versioned app registry;
# if we directly import it, it'll be the wrong version
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).bulk_create([
Country(name="USA", code="us"),
Country(name="France", code="fr"),
])
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(forwards_func, lambda apps, schema_editor: None),
]
Це працює для Django 1.8, 1.9
Оновлення: Кращий спосіб написання цього було б замінити lambda apps, schema_editor: None
з migrations.RunPython.noop
в сниппета вище. Це обоє функціонально одне і те ж. (заслуга в коментарях)
RunPython.noop
замість вбудованої лямбда або еквівалент: docs.djangoproject.com/en/1.8/ref/migration-operations/…
migrations.RunPython(forwards_func, migrations.RunPython.noop)
. Потрібно перевірити це функціонально. Це має бути додано як відповідь чи редагування до цього колись.
Ось моє рішення, оскільки вищевказане рішення насправді не охоплює випадок використання, коли ви використовуєте RunPython
.
Ви можете отримати доступ до таблиці через ORM за допомогою
from django.db.migrations.recorder import MigrationRecorder
>>> MigrationRecorder.Migration.objects.all()
>>> MigrationRecorder.Migration.objects.latest('id')
Out[5]: <Migration: Migration 0050_auto_20170603_1814 for model>
>>> MigrationRecorder.Migration.objects.latest('id').delete()
Out[4]: (1, {u'migrations.Migration': 1})
Таким чином, ви можете запитувати таблиці та видаляти ті записи, які є для вас релевантними. Таким чином ви можете детально модифікувати. Під час RynPython
міграцій потрібно також дбати про дані, які додавали / змінювали / видаляли. Наведений вище приклад лише показує, як ви отримуєте доступ до таблиці за допомогою Djang ORM.
django.db.utils.ProgrammingError: relation "<relation name>" already exists
отже, я зробив migrate --fake
неправильне, тому я спробував повернутися назад, тоді я отримав psycopg2.ProgrammingError: relation "<other <relation name>" does not exist
СПАСИБО
Інша річ, яку ви можете зробити - це видалити створену вручну таблицю.
Поряд з цим вам доведеться видалити саме цей файл міграції. Крім того, вам доведеться видалити той конкретний запис у таблиці міграцій django (можливо, останній у вашому випадку), який співвідноситься з певною міграцією.
Не видаляйте файл міграції до моменту реверсії. Я зробив цю помилку, і без файлу міграції база даних не знала, які речі видалити.
python manage.py showmigrations
python manage.py migrate {app name from show migrations} {00##_migration file.py}
Видаліть файл міграції. Після того, як потрібна міграція у ваших моделях ...
python manage.py makemigrations
python manage.py migrate
Я зробив це в 1.9.1 (щоб видалити останню або останню створену міграцію):
rm <appname>/migrations/<migration #>*
приклад: rm myapp/migrations/0011*
увійшли в базу даних і запустили цей SQL (постгреси в цьому прикладі)
delete from django_migrations where name like '0011%';
Тоді мені вдалося створити нові міграції, які почалися з міграційного номера, який я щойно видалив (у даному випадку 11).
Ця відповідь стосується подібних випадків, якщо головна відповідь Alasdair не допомагає . (Наприклад, якщо небажана міграція створюється незабаром знову з кожною новою міграцією або якщо вона перебуває в більшій міграції, яку неможливо повернути або таблицю видалити вручну.)
... видалити міграцію, не створюючи нової міграції?
TL; DR : Ви можете видалити кілька останніх повернених (заплутаних) міграцій та зробити новий після виправлення моделей . Ви також можете використовувати інші методи, щоб налаштувати його не створювати таблицю за допомогою команди migrate. Остання міграція повинна бути створена так, щоб вона відповідала поточним моделям .
Випадки, чому хтось не хоче створити таблицю для моделі, яка повинна існувати:
A) Жодна така таблиця не повинна існувати ні в базі даних, ні на машині, ні в умовах
class Meta: abstract = True
Б) Таблиця створюється рідко, чимось іншим або спеціальним чином вручну.
class Meta: managed = False
C) Таблиця використовується лише на деяких машинах (наприклад, у розробці).
class Meta: managed = some_switch
.D) Проект використовує декілька баз даних уsettings.DATABASES
allow_migrate
, щоб диференціювати бази даних, де слід створити таблицю, а де ні.Міграція створюється у всіх випадках A), B), C), D) з Django 1.9+ (і лише у випадках B, C, D з Django 1.8), але застосовується до бази даних лише у відповідних випадках або, можливо, ніколи, якщо потрібно так. Міграція необхідна для запуску тестів з Джанго 1.8. Повний відповідний поточний стан реєструється міграціями навіть для моделей з керованою = False в Django 1.9+, щоб можна було створити ForeignKey між керованими / некерованими моделями або зробити модель керованою = True пізніше. (Це питання було написане під час Django 1.8. Тут все має бути дійсним для версій від 1.8 до поточних 2.2.)
Якщо остання міграція (є) не легко перетворюється, можна обережно (після резервного копіювання бази даних) зробити підроблене відновлення ./manage.py migrate --fake my_app 0010_previous_migration
, видалити таблицю вручну.
При необхідності створіть фіксовану міграцію з нерухомої моделі та застосуйте її, не змінюючи структури бази даних ./manage.py migrate --fake my_app 0011_fixed_migration
.
Якщо під час повернення назад міграції ви стикаєтеся з проблемою, і хоч якось зіпсували її, ви можете виконати fake
міграцію.
./manage.py migrate <name> --ignore-ghost-migrations --merge --fake
Для версії django <1.7 це створить запис у south_migrationhistory
таблиці, його потрібно видалити.
Тепер ви зможете легко повернути міграцію.
PS: Я застряг багато часу, і фальшива міграція, а потім повернення назад допомогло мені.