背景
業務でDjangoを使っています。
MySqlで直接テーブルを削除したのですが、migrateしてもテーブルが再作成されなかったです。
それで以下の投稿記事の「マイグレーション管理用のテーブルで履歴を削除すること」で解決しましたが内容を整理します。
このブログの作者はフロントエンドにweightをかけ過ぎている者です😇
温かい目で見守って頂けると助かります
Model
Model(モデル)は1つのデータベーステーブルにマッピングされます
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
first_name と last_name はモデルのフィールドです。
各フィールドはクラス属性として指定され、各属性はデータベースのカラムにマッピングされます。
上記のPersonモデルは以下のようなデータベーステーブル(Mysql)を作成します。
CREATE TABLE myapp_person (
`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`first_name` VARCHAR(30) NOT NULL,
`last_name` VARCHAR(30) NOT NULL
);
Migration
モデルに加えた変更(フィールドの追加、モデルの削除など)を データベーススキーマに反映させます
コマンド
migrate
データベースにマイグレーションの適用と適用解除を行います
python manage.py migrate
makemigrations
モデルに加えた変更に基づいて新しいマイグレーションを作成します
python manage.py makemigrations
sqlmigrate
マイグレーションのSQL文を表示します
python manage.py sqlmigrate
以下はサンプルですか、このように表示されるそうです
python manage.py sqlmigrate historical_data 0001
BEGIN;
--
-- Create model PriceHistory
--
CREATE TABLE "historical_data_pricehistory" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"date" datetime NOT NULL,
"price" decimal NOT NULL,
"volume" integer unsigned NOT NULL
);
COMMIT;
showmigrations
プロジェクトのマイグレーションとそのステータスを一覧表示します
python manage.py showmigrations
makemigrations
モデルの変更を個々のマイグレーションファイル(コミットに似ています)にパッケージ化します
python manage.py makemigrations
Dependency
マイグレーションクラスの依存関係リストには、このマイグレーションを適用する前に適用しなければならないマイグレーションが含まれます。
Operation
Modelが過去にどのような状態であったかを調べ、前回のMigration以降でModelに加えた変更を計算し、Migrationファイルを自動的に書くことができます。
マイグレーションを適用すると、各オペレーションは特定のデータベースに必要なSQL文を生成します。
django_migrations
Djangoはdjango_migrationsというテーブルをマイグレーション管理用に使います。
Djangoは、最初にマイグレーションを適用するときに、自動的にこのテーブルをデータベースに作成します。
マイグレーションがapplyされたり、 fakeされたりするたびに新しい行がテーブルに挿入されます。
次にマイグレーションが実行されるとき、 django_migrationsテーブルに登録されたマイグレーションをスキップします。
つまり、既に適用されているマイグレーションファイルを手動で変更しても、データベースにそのマイグレーションの履歴がある限り、Djangoはその変更を無視します。
テーブルから対応するマイグレーション履歴を削除することで、Djangoを騙してマイグレーションを再実行させることもできます。
これはめったに良い考えではなく、マイグレーションシステムが壊れたままになってしまう可能性があります。
Djangoがモデルの変更を検出する方法
Djangoは適用された全てのマイグレーションを調べ、モデルがどうあるべきかのプロジェクト状態を構築します。
このプロジェクト状態は現在のモデル定義と比較され、適用されるとプロジェクト状態をモデル定義に合わせて最新の状態にする一連の操作のリストが作成されます。
チェスの例
あなたのモデルをチェスの盤のように考えることができ、Djangoはチェスのグランドマスターとしてあなたの対戦を見守ります。しかし、グランドマスターはあなたの一挙手一投足を見ているわけではありません。グランドマスターが盤を見るのは、あなたがmakemigration
叫ぶときだけです。
可能な手は限られているので(そしてグランドマスターはグランドマスターなので)、彼女は最後に盤面を見てから起こった手を思いつくことができる。彼女はいくつかのメモを取り、あなたが再びmakemigration
の声を上げるまでプレーさせる。
次に盤面を見るとき、グランドマスターは前回のチェス盤がどうなっていたかを覚えていないが、前の手のメモを調べて、チェス盤がどうなっていたかのメンタルモデルを構築することができます。
migrare
を叫ぶと、グランドマスターは記録されたすべての手を別のチェス盤で再生し、どの記録がすでに適用されているかをスプレッドシートに記録する。この2つ目のチェス盤があなたのデータベースで、スプレッドシートが django_migrationsテーブルです
テーブルをSQLで直接削除してしまった場合にどうすれば良かったのか
django_migrationsテーブルの履歴を削除してはいけなかった
というのは前の章で述べてますので本来どうするべきだったかを考えます。
マイグレーション地点を戻すためにDROP TABLEを呼ぶ可能性を考えると、テーブルが削除済みなために失敗
上の投稿ではマイグレーションを戻すことに失敗していました
以下を考えました
マイグレーションを戻す前にSQLで削除したテーブルをSQLで直接作成する
↓
マイグレーションを戻す
↓
テーブルが削除される
↓
django_migrationsテーブルの履歴を操作しないで済む
最後に
- Django,バックエンドのことはまださっぱりわからないですが、少しづつ力をつけたいです
- migrationファイルを削除して一つのファイルにまとめたことがありましたがこれも推奨されないことをしていたんだなと痛感しました