Я выполнил миграцию, добавив новую таблицу, и хочу отменить ее и удалить миграцию, не создавая новую миграцию.
Как это сделать? Есть ли команда, чтобы отменить последнюю миграцию, и тогда я могу просто удалить файл миграции?
Я выполнил миграцию, добавив новую таблицу, и хочу отменить ее и удалить миграцию, не создавая новую миграцию.
Как это сделать? Есть ли команда, чтобы отменить последнюю миграцию, и тогда я могу просто удалить файл миграции?
Ответы:
Вы можете вернуться, перейдя к предыдущей миграции.
Например, если последние две миграции:
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
используя имя приложения и имя миграцииНо следует отметить, что не все миграции можно повернуть вспять. Это происходит, если у Django нет правила для аннулирования. Для большинства изменений, на которые вы автоматически произвели миграцию ./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-migrations (возможно, последнюю в вашем случае), которая соответствует этой конкретной миграции.
Не удаляйте файл миграции до тех пор, пока не вернетесь. Я сделал эту ошибку и без файла миграции, база данных не знала, что удалить.
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 (postgres в этом примере)
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), но применяется к базе данных только в соответствующих случаях или, возможно, никогда, если требуется так. Миграции были необходимы для запуска тестов начиная с Django 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: я застрял на долгое время, и мне пришлось выполнить ложную миграцию, а затем вернуться назад.