Django
Django は Python で利用できるWebアプリケーションフレームワークであり、多機能なコンポネントで構成されています。データモデルにおいても、クエリ文を一切書くことなくデータベースの生成・データ取得・更新・削除などを行うことができ、非常に便利です。
しかしその一方で、何度もカラムを追加・削除したり外部キーなども含めた複雑なテーブルを構成したりすると、データの整合性が保てなくなり migrate しようにもエラーでどうにもならなくなることもあります。
そんなとき、
- 手動で migrate を戻す
- データベースのリセット
- migrate ファイルの初期化
手動で migrate を戻す
今回は、 Django のチュートリアルにならって、 poll/models.py に Question クラスと Choice クラスを追加した後に migrate したとしましょう。https://docs.djangoproject.com/ja/3.2/intro/tutorial02/
migrate した情報は、「 django_migrations 」テーブルに書き込まれます。
つまりこのデータを削除すれば、元に戻せることになります。しかし、今回のケースではテーブルを追加する内容であったため、該当する
- polls_choice
- polls_question
手動で migrate を完全に戻す
上記の方法でも再度同じテーブルを作成するのであれば問題ありません。しかし、モデルやテーブルが変わるようなクラス名などの変更がある場合は、- sqlite_master
- django_content_type
- auth_permission
- sqlite_sequence
sqlite_master テーブルには実行する DDL 文が格納されています。 migrate を戻す対象のレコードを削除しましょう。
django_content_type テーブルには、アプリとモデルの関連を記しています。これらも該当モデルを削除しましょう。
auth_permission テーブルには、追加したモデルの権限が記されています。該当モデルのレコードを削除しましょう。
sqlite_sequence テーブルには、上記のテーブルなどのシーケンスを発行するため数値が進んでいます。削除した件数だけ元にもどしましょう。今回の場合ですと、「 django_migrations 」を 18 に、「 django_content_type 」を 6 に、「 auth_permission 」を 24 にするといいでしょう。
これで元の状態に戻りました。
データベースのリセット
いろいろと考えるのが面倒な場合は、 MySQL の場合だと全テーブルを削除、 SQLite の場合だとデータベースのファイルを削除するといいでしょう。もし必要なデータがある場合は、事前に Insert 文などを作成しておくといいでしょう。 MySQL だと mysqldump で一発で出力できますね。
migrate ファイルの初期化
データベースをいろいろと変更しすぎて migrate するためのファイルが煩雑になってしまった場合、まだリリースしていない開発段階なのであれば、いっそのこと各アプリケーションの migrations フォルダのファイルを削除して makemigrations を最初からやり直すのも手ですね。すると無駄な migrate のファイルがなくなりますので、migrate がスッキリします。ただし他にも開発者がいる場合は、他の方にも確認を取ってから実行してください。基本的に migrate のファイルは変更しないのが鉄則ですので、 migrate ファイルをリセットする場合は、他の開発者の環境でも同様な手順を取る必要があります。危険な香りもしますが私の場合、結合テストに入る前に一度 migrate ファイルを初期化することが多いです。結合テストに入る前であれば、ほぼほぼテーブル仕様が固まっているので、一旦リセットして本番環境で無駄な処理をさせないことを目的としています。今までこれによりトラブルが発生したことはありません。