【Django1.4】Djangoでモデルのフィールドを途中で追加・変更・削除する方法

したいこと

一度モデル作ってsyncdbしたが、やっぱり途中で色々変えたくなった

解決策の例

  1. テーブルを削除して作り直し、manage.py syncdb
  2. ALTER文で直接テーブルを書き換える

ちなみに1の方法だとデータが消えてしまうので、とっても手軽ではあるが公開前にしか使えない。(削除する前にバックアップをとって…というやり方も見つけた。)

ALTER文で直接テーブルを書き換える手順

  • app名はtwitter
  • テーブル名はtwitter_status(dbshellで\dで確認。'appname_modelname'の形)
  • 例として、もう作ってしまったテーブルにCharFieldとIntegerFieldを追加する。
  • 環境はPostgreSQL

流れ

  • models.py を修正
…
retweet_count = models.IntegerField(default=0)
in_reply_to_status_id_str = models.CharFields(max_length=20, blank=True)
…
  • しなくてもいいが、manage.py sql twittersql文を確認(最終的にフィールドを以下の形にする)
…
"retweet_count" integer NOT NULL,
"in_reply_to_status_id_str" varchar(20) NOT NULL,
…
  • manage.py dbshellでALTER文をNULLを許容する形で発行
ALTER TABLE twitter_status ADD retweet_count integer;
  • デフォルト値を与える
ALTER TABLE twitter_status ALTER COLUMN retweet_count SET DEFAULT 0;
  • UPDATE文で追加のフィールドに値を与える(既存のレコードにはデフォルト値が与えられていない)
UPDATE twitter_status SET retweet_count=0 WHERE retweet_count is NULL;
  • ALTER文でNOT NULLをSET
ALTER TABLE twitter_status ALTER COLUMN retweet_count SET NOT NULL;
  • retweet_countが追加できた。
  • 今度はin_reply_to_status_id_strを追加する。やることは全く一緒。
  • NULLを許容する形でADD
ALTER TABLE twitter_status ADD in_reply_to_status_id_str varchar(20);
  • default値の設定
ALTER TABLE twitter_status ALTER COLUMN in_reply_to_status_id_str SET DEFAULT ''; 
  • UPDATE
UPDATE twitter_status SET  in_reply_to_status_id_str='' WHERE in_reply_to_status_id_str is NULL;
  • SET NOT NULL
ALTER TABLE twitter_status ALTER COLUMN in_reply_to_status_id_str SET NOT NULL;
  • in_reply_to_status_id_strの追加完了