Djangoのモデルにフィールドを追加する時のフロー
どんなに入念にデータベースを設計しても、機能を追加していく過程でどうしても新しいカラムを追加せざるを得ない場面に遭遇することが起こります。
テーブルごと作り直せれば話は早いのですが、すでにシステムが稼働しているためにそれができない場合、もう少し複雑なことをしなければいけません。
DjangoでModelに新しいFieldを追加した場合に、行うフローを備忘録として記します。
Fieldの変更・追加
myappアプリケーションのMyModelというモデルにnewfieldというカラムを追加する場合。新しく追加するカラムはnull=Trueをセットしておく。これは、カラムを追加する時にnull制約に引っかからないようにするためなので、他にもdefaultを設定するなどの方法で回避してもOK
from django.db import models class MyModel(models.Model): oldfield = models.CharField(max_length=10) newfield = models.CharField(max_length=13, null=True)
SQLを確認
manage.pyのsqlコマンドでテーブルのCREATE文を出力する。
$ ./manage.py sql myapp
出力
BEGIN; CREATE TABLE `myapp_mymodel` ( `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `oldfield` varchar(10) NOT NULL, `newfield` varchar(13) ) ; COMMIT
ALTER TABLEでテーブル構造を変更する
テーブル構造を変更する。MySQLの場合は
/* ADD以下は上で出力したCREATE文の対応する部分をコピペ */ ALTER TABLE `myapp_mymodel` ADD `newfield` varchar(13);
データを挿入
myapp_mymodelテーブルの既存データにnewfieldの値を正しくUPDATEする。
Fieldの制約を正しくセットしなおす
今度は本気の制約を設定する
from django.db import models class MyModel(models.Model): oldfield = models.CharField(max_length=10) newfield = models.CharField(max_length=13)
再びCREATE文を出力
$ ./manage.py sql myapp
出力
BEGIN; CREATE TABLE `myapp_mymodel` ( `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `oldfield` varchar(10) NOT NULL, `newfield` varchar(13) NOT NULL ) ; COMMIT
再びALTER TABLE
/* ADD以下は上で出力したCREATE文の対応する部分をコピペ */ ALTER TABLE `myapp_mymodel` ADD `newfield` varchar(13) NOT NULL;
移行完了
これで完了。データベースにそんなに詳しくないので、あまり正しい方法ではないかも。
その他の注意点
- 本番環境を変更する前に、開発環境で十分に練習すること
- できるかぎりバッチ処理の形にして、操作ミスなどが入らないようにする
- このやり方を行うには、本番環境をメンテナンスのために一時停止する必要がある