FrontPage

tips

initial_dataは使うべきか否か

migrateコマンドを実行する毎にinitial_dataが読み込まれる。 initial_dataは最新のデータベース定義に合わせて作成を行う(ですよね?)ため、 ゼロスタートでマイグレーションを開始すると最初期のマイグレーションではinitial_dataが読めない事象が発生。

south-usersのディスカッションでは initial_dataを作成しないことをオススメ している。

PostgreSQL上での定義変更とデータ変更

schema migrationとdata migrationを **同時に行ってはいけない** 。

Southはどうやらforward migrationを1つのトランザクションで実行するようですが、 PostgreSQLを利用している場合、スキーマ変更とデータ変更を同時に行うことが出来ない。

回避策としては次のようにする。

    def forwards(self, orm):
        # Adding field 'Shop.new_column'
        db.start_transaction()
        db.add_column('shop_shop', 'new_column',
                      self.gf('django.db.models.fields.CharField')(max_length=32, null=True),
                      keep_default=False)
        db.commit_transaction()

        db.start_transaction()
        if not db.dry_run:
            shop_model = orm['shop.Shop']
            for shop in shop_model.objects.all():
                shop.new_column = 'new value'
                shop.save()
        db.commit_transaction()

       db.alter_column('shop_shop', 'new_column', self.gf('django.db.models.fields.CharField')(unique=True, max_length=32))
        db.create_unique('shop_shop', ['new_column'])

south初期化

pip install southしてsettings.INSTALLED_APPSにsouthを追加。manage.py syncdbする。

既存アプリをsouth管理にする

./manage.py convert_to_south appname

これでinitialファイルが作成される。

スキーママイグレーション

データベースのDDLマイグレーションを行う。

southをアプリに適用

アプリのモデルをsouthで管理するように変更する。

./manage.py schemamigration appname --initial

appname/migrations/0001_initial.py が作成される。これがテーブルを生成する際の定義になる。

モデルの変更

south適用済みのアプリで通常通りにモデルを編集する。syncdbを行わない限り次の状態になる。

  • アプリのモデル定義 → 新しい
  • データベース上のスキーマ → 古いまま(カラムなどが足りない)

そのままmodels.pyを変更する。スキーマ変更をsouthに伝えるにはschemamigrationオプションを使う。

./manage.py schemamigration appname --auto

0002_hogehoge.pyなどが作成される(add_column〜など意味のあるファイル名になる)。数値の部分は連番。

外部キーの追加、削除

手動で外部キーを追加する話。

datamigrationコマンドで空のファイルを追加して、forwards()にdb.alter_column()を定義する。 modelsプロパティのカラム定義も同じファイル内で定義しておくこと(これがないと以降のマイグレーションが混乱するので)。

class Migration(DataMigration):
    def forwards(self, orm):
        db.alter_column('frame_frame', 'shop_id', models.ForeignKey(orm['shop.Shop'], null=True, blank=True, on_delete=models.SET_NULL))
    def backwards(self, orm):
       "Write your backwards methods here."
       db.delete_foreign_key('frame_frame', 'shop_id')
    models = {
       'frame.frame': { # 一部抜粋
           'shop': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shop.Shop']", 'null': 'True', 'blank': 'True', 'on_delete': 'models.SET_NULL'}),
        }
    }

データマイグレーション

データマイグレーションを行うにはdatamigrationオプションを使う。 アプリ名とマイグレーション名(適当でOK)を入力するとマイグレーション用スケルトンが作成される。

./manage.py datamigration appname migration_name
Created 0002_migration_name.py.

このファイルにはforwards(), backwards()メソッドが定義されていて、 メソッド内にデータ移行処理を記述する。

マスタデータ追加のような単純な処理であれば次のようにする。 ormオブジェクト経由でアクセスする。

def forwards(self, orm):
    orm.HogeModel.objects.create(title=u'T900素材', sort_order=0)

マイグレーション対象のアプリ以外のモデルにアクセスする場合には、 orm['appname.modelname']という辞書からアクセスする。 例えばdjango.contrib.auth.models.Userにアクセスするのであれば次のようになる。

def forwards(self, orm):
    for answer in orm.Answer.objects.all():
       answer.user = orm['auth.User'].objects.get(name=u'hogehoge')
       answer.save()

動作中の非south環境へsouthを導入する

次のような環境にsouthを導入するには。

  • データベースは既存のスキーマで稼働中
  • 今後の新規、更新をsouthで管理したい

southを導入する

先の手順に従いsouthをインストールしてsyncdbするだけ。

稼働中のモデルでinitial用マイグレーションを作成

各アプリにsouthを適用する。

./manage.py schemamigration appname --initial

モデルの変更を行い、適用する

すでに稼働中のモデルがあるのでinitialをスキップする必要がある。 initialを実行したものとして取り扱うには--fakeオプションを利用する。

次の例は0001のマイグレーション(たいていはinitial)を実行済みとしてマークする。

./manage.py migrate appname 0001 --fake

これ以後は必要なマイグレーションを適用する。

./manage.py migrate appname 0002

マイグレーションの内容をまっさらにする

zeroオプションを使う

./manage.py migrate appname zero

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-08-25 (日) 16:08:01 (1370d)