2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

背景

業務で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
);

models

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

migrations

Dependency

マイグレーションクラスの依存関係リストには、このマイグレーションを適用する前に適用しなければならないマイグレーションが含まれます。

Operation

Modelが過去にどのような状態であったかを調べ、前回のMigration以降でModelに加えた変更を計算し、Migrationファイルを自動的に書くことができます。
マイグレーションを適用すると、各オペレーションは特定のデータベースに必要なSQL文を生成します。

migration-operations

django_migrations

Djangoはdjango_migrationsというテーブルをマイグレーション管理用に使います。
Djangoは、最初にマイグレーションを適用するときに、自動的にこのテーブルをデータベースに作成します。
マイグレーションがapplyされたり、 fakeされたりするたびに新しい行がテーブルに挿入されます。

次にマイグレーションが実行されるとき、 django_migrationsテーブルに登録されたマイグレーションをスキップします。
つまり、既に適用されているマイグレーションファイルを手動で変更しても、データベースにそのマイグレーションの履歴がある限り、Djangoはその変更を無視します。

テーブルから対応するマイグレーション履歴を削除することで、Djangoを騙してマイグレーションを再実行させることもできます。
これはめったに良い考えではなく、マイグレーションシステムが壊れたままになってしまう可能性があります。

Djangoがモデルの変更を検出する方法

Djangoは適用された全てのマイグレーションを調べ、モデルがどうあるべきかのプロジェクト状態を構築します。
このプロジェクト状態は現在のモデル定義と比較され、適用されるとプロジェクト状態をモデル定義に合わせて最新の状態にする一連の操作のリストが作成されます。

チェスの例

あなたのモデルをチェスの盤のように考えることができ、Djangoはチェスのグランドマスターとしてあなたの対戦を見守ります。しかし、グランドマスターはあなたの一挙手一投足を見ているわけではありません。グランドマスターが盤を見るのは、あなたがmakemigration叫ぶときだけです。

可能な手は限られているので(そしてグランドマスターはグランドマスターなので)、彼女は最後に盤面を見てから起こった手を思いつくことができる。彼女はいくつかのメモを取り、あなたが再びmakemigrationの声を上げるまでプレーさせる。

次に盤面を見るとき、グランドマスターは前回のチェス盤がどうなっていたかを覚えていないが、前の手のメモを調べて、チェス盤がどうなっていたかのメンタルモデルを構築することができます。

migrareを叫ぶと、グランドマスターは記録されたすべての手を別のチェス盤で再生し、どの記録がすでに適用されているかをスプレッドシートに記録する。この2つ目のチェス盤があなたのデータベースで、スプレッドシートが django_migrationsテーブルです

image.png

テーブルをSQLで直接削除してしまった場合にどうすれば良かったのか

django_migrationsテーブルの履歴を削除してはいけなかったというのは前の章で述べてますので本来どうするべきだったかを考えます。

マイグレーション地点を戻すためにDROP TABLEを呼ぶ可能性を考えると、テーブルが削除済みなために失敗

上の投稿ではマイグレーションを戻すことに失敗していました
以下を考えました

マイグレーションを戻す前にSQLで削除したテーブルをSQLで直接作成する

マイグレーションを戻す

テーブルが削除される

django_migrationsテーブルの履歴を操作しないで済む

最後に

  • Django,バックエンドのことはまださっぱりわからないですが、少しづつ力をつけたいです
  • migrationファイルを削除して一つのファイルにまとめたことがありましたがこれも推奨されないことをしていたんだなと痛感しました

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?