web-dev-qa-db-ja.com

Django 1.8:既存のスキーマの初期移行を作成する

移行システムを使用するDjango 1.8プロジェクトを開始しました。
どうやら物事が面倒になったので、移行フォルダーとテーブルをDBから消去しましたが、今は成功せずに再構築しようとしています。

3つのアプリ(3 models.pyファイル)があり、モデルはテーブルを正確に反映しています!

私がこれまでに見つけた最良のアプローチは次のとおりです。

  1. すべてのmigrationsフォルダーを消去します。できた!
  2. Django_migrationsテーブルからすべてを削除します。できた!
  3. すべてのアプリに対してpython manage.py makemigrations --empty <app>を実行します。できた!
  4. python manage.py migrate --fakeを実行します。できた! (ただし、すべてのmakemigrationsコマンドの後に実行した場合にのみ機能します。

新しいフィールドを追加し、makemigrationsコマンドを実行すると、次のエラーが表示されます。
Django.db.utils.OperationalError: (1054, "Unknown column 'accounts_plan.max_item_size' in 'field list'")

私はこのことについて何時間も燃やしてきました。毎回移行を中断せずに作業を継続できるように、移行を初期化するにはどうすればよいですか?

なぜそんなに複雑なのですか?なぜ単純なワンライナーがありません:initiate_migrations_from_schema

編集:
今では物事はさらに厄介になります。 Django_migrationsテーブルを切り捨て、migrationsフォルダーをすべて削除しました。
今、python manage.py migrate --fake-initial(DEVドキュメントで見つけたもの)を実行しようとしていますが、Djangoのすべての「内部」アプリ(認証、セッションなど)をセットアップするだけです。
(1054, "Unknown column 'name' in 'Django_content_type'")
現在、この「列」は実際の列ではありません。 Djangoのcontenttypesアプリで定義されている@propertyです。 ISは何ですか? nameプロパティを実際の列として識別するのはなぜですか?

69
user1102018

ついに機能するようになりましたが、その理由はわかりませんが、将来的に機能することを願っています。
多数のトライアルを行い、Djangoの開発サイトを通過した後( link )。
手順は次のとおりです(この問題が発生した場合)。

  1. Django_migrationsテーブルを空にします:delete from Django_migrations;
  2. すべてのアプリについて、migrationsフォルダーを削除します:rm -rf <app>/migrations/
  3. 「組み込み」アプリの移行をリセットします:python manage.py migrate --fake
  4. アプリを実行するたびに:python manage.py makemigrations <app>。依存関係に注意してください(ForeignKeyのあるモデルは、親モデルの後に実行する必要があります)。
  5. 最後に:python manage.py migrate --fake-initial

その後、念のため、--fake-initialフラグなしで最後のコマンドを実行しました。

これですべてが機能し、移行システムを通常どおり使用できます。

この問題に遭遇したのは私だけではないはずです。より適切に文書化し、さらには簡素化する必要があります。

Django 1.9ユーザーの更新:
再びこのシナリオでDjango 1.9.4を使用し、ステップ5が失敗しました。
私がしなければならなかったのは、--fake-initial--fakeに置き換えて機能させることだけです。

161
user1102018

私はこのシナリオに遭遇しましたが、解決するためにデータベースをドロップする必要はありませんでした。通常、アプリから移行フォルダを削除し、データベースから移行エントリを削除します。

私は一度に1つのアプリで移行を実行しようとします。アプリのいずれかが他のテーブルに依存している場合、明らかに最後に追加します。

また、私は通常、単に実行しますpython manage.py makemigrations次にちょうどpython manage.py migrate最初の移行でも、Django 1.7で正常に動作するはずです1.8.

2
Chris Hawkes

Django ...、1.8、1.9、...

達成したいのは、既存の移行を無効にし、それらの代替を使用することです。

リリース時にコマンドを使用せずに正しく実行する方法(データベースと同僚に影響を与えないケース)。

  1. すべてのアプリについて、その移行フォルダーを取り除きます:mv <app>/migrations/ <app>/migrationsOLD/

  2. アプリを実行するたびに:python manage.py makemigrations <app>

  3. 新しい移行をそれぞれカスタマイズします。

    • CircularDependencyErrorまたはValueError: Unhandled pending operations for modelsを避けるために、複雑なアプリ、またはそれらの間に複数のアプリと関連モデルがある場合:

      <app>0002_initial2.pyで2番目の空の移行を準備します(app_other::0001_initial.pyおよび<app> :: 0001_initial.pyにも依存関係を置きます-で作成されたすべてのForeignKey、M2M 0001他のアプリの移行手順)

      すべての順序を整える必要があります-準備のためにさらに移行が必要になる場合があります。ここで、各移行でdependencies属性に注意してください。

    • 初期値に注意してください-RunPythonからのmigrationsOLDアクションをすべて確認し、必要に応じてコードを新しい初期移行にコピーしてください。

    • --fake-initialのオプション)initial=Trueをすべての新しい移行クラスに追加します(追加された場合は0002も)。

    • 新しいMigrationクラスにreplaces属性を追加します。 (独自のカスタムsquashmigrationsなど)。 <app>からの古い移行をすべてそこに配置します
  4. makemigrationsですべてを確認します。

    「変更は検出されませんでした」とアサートします

  5. migrate -lが[x]をどこにでも表示するかどうかを確認します

    同様のアサート:

    [X] 0001_initial

    [X] 0002_initial2(102押しつぶされた移行)

例:

古い場合:

0001_initial.py
0002_auto.py
...
0103_auto.py

準備する:

0001_initial.py
0002_initial2.py  (optional but sometimes required to satisfy dependency)

最後のreplacesに追加します(ここでは0002、0001でも可):

replaces = [(b'<app>', '0002_auto.py'), ..., (b'<app>', '0103_auto.py')]

0001_initial.pyは、古い名前と同じ名前にする必要があります。

0002_initial2.pyは新しいものですが、古い移行の代わりになるため、Djangoはそれをロード済みとして扱います。

2

ルーターを使用している場合、そこに問題がある可能性があります。 allow_migrateで正しい方法で実行されている場合は、メソッドrouters.pyを確認します。戻り値を常にTrueに設定し、問題が解決するかどうかを確認してください。

def allow_migrate(self, db, app_label, model_name=None, **hints):
    return True
0
AmirM