web-dev-qa-db-ja.com

djangoが最後の移行を元に戻す

新しい移行を作成せずに、新しいテーブルを追加して元に戻して移行を削除する移行を実行しました。

どうすればいいのですか?最後の移行を元に戻すコマンドがあり、その後移行ファイルを単に削除できますか?

325
Ronen Ness

以前の移行に移行することで元に戻すことができます。

たとえば、最後の2回の移行が次のようになっているとします。

  • 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
583
Alasdair

Alasdairによる答えは基本をカバーしています

  • 必要なマイグレーションを./manage.py showmigrationsで識別します
  • アプリ名と移行名を使用したmigrate

しかし、すべてのマイグレーションを逆転できるわけではないことを指摘しておくべきです。これは、Djangoが逆転する規則を持っていない場合に起こります。 ./manage.py makemigrationsによって自動的に移行を行ったほとんどの変更では、元に戻すことが可能です。ただし、カスタムスクリプトでは、次の例に示すように、順方向と逆方向の両方を記述する必要があります。

https://docs.djangoproject.com/en/1.9/ref/migration-operations/ /

ノーオペレーションリバースを行う方法

もしあなたがRunPython操作をしていたのなら、論理的に厳密な反転スクリプトを書かずにマイグレーションを取り消したいだけかもしれません。次のdocs(上のリンク)からの例へのクイックハックはこれを可能にし、データベースを逆にした後でも、マイグレーションが適用された後と同じ状態にします。

# -*- 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: Nonemigrations.RunPython.noopに置き換えることでしょう。どちらも機能的には同じものです。 (コメントへのクレジット)

28
AlanSE

他にできることは、手動で作成したテーブルを削除することです。

それに伴い、その特定の移行ファイルを削除する必要があります。また、 Django-migrationsテーブルのその特定のエントリを削除する必要があります その特定の移行に関連する(おそらくあなたのケースでは最後のもの)。

9
sprksh

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を介してテーブルにアクセスする方法を示しています。

6
Özer S.

1.9.1でこれを行いました(最後または最後に作成されたマイグレーションを削除するため)。

  1. rm <appname>/migrations/<migration #>*

    例: rm myapp/migrations/0011*

  2. データベースにログインしてこのSQLを実行した(この例ではpostgres)

    delete from Django_migrations where name like '0011%';

その後、削除したばかりの移行番号(この場合は11)から始まる新しい移行を作成できました。

5
MIkee

この回答は、同様の場合に当てはまりますAlasdairのトップの回答が役に立たない場合。 (たとえば、新しい移行ごとに不要な移行がすぐに再び作成される場合、または元に戻せない大きな移行である場合、またはテーブルが手動で削除されている場合)

...新しい移行を作成せずに移行を削除しますか?

TL; DR:最後に戻された(混乱した)移行をいくつか削除して、新しい移行を行うことができますモデルの修正後。また、他の方法を使用するを構成してテーブルを作成しない migrateコマンドを使用することもできます。 現在のモデルと一致するように、最後の移行を作成する必要があります


ケース存在しなければならないモデルのテーブルを誰も作成したくない理由:

A)そのようなテーブルは、マシンや条件のないデータベースには存在しないはずです。

  • When:これは、他のモデルのモデル継承のためにのみ作成された基本モデルです。
  • Solution:Set class Meta: abstract = True

B)テーブルは、他の何かによって、または特別な方法で手動で作成されることはめったにありません。

  • 解決策:class Meta: managed = Falseを使用
    移行は作成されますが、使用されることはなく、テストでのみ使用されます。移行ファイルは重要です。そうしないと、再現可能な初期状態からデータベーステストを実行できません。

C)このテーブルは、一部のマシンでのみ使用されます(開発中など)。

  • 解決策:特別な条件下でのみINSTALLED_APPSに追加される新しいアプリケーションにモデルを移動するか、条件付き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以降、テストの実行には移行が必要でした。 Django 1.9+のmanaged = Falseのモデルでも、完全な関連する現在の状態が移行によって記録され、マネージド/アンマネージドモデル間でForeignKeyを作成したり、後でモデルをmanaged = Trueにしたりできます。 (この質問はDjango 1.8の時点で書かれています。ここにあるものはすべて1.8から現在の2.2までのバージョンで有効です。)

最後の移行が簡単に元に戻せない場合は、(データベースのバックアップ後に)注意して fake revert./manage.py migrate --fake my_app 0010_previous_migrationを実行し、テーブルを手動で削除することができます。

必要に応じて、固定モデルから固定移行を作成し、データベース構造./manage.py migrate --fake my_app 0011_fixed_migrationを変更せずに適用します。

3
hynekcer

もしあなたが移行を元に戻している間に問題に直面していて、そしてどういうわけかそれをめちゃくちゃにしたなら、あなたはfake移行を実行することができます。

./manage.py migrate <name> --ignore-ghost-migrations --merge --fake

Djangoバージョン<1.7 これでsouth_migrationhistoryテーブルにエントリが作成されますので、そのエントリを削除する必要があります。

これで、移行を簡単に元に戻すことができます。

シモンズ:私は長い間立ち往生していて、偽の移行を実行してから元に戻すことが私を助けてくれました。

0
Pransh Tiwari