django migrate コマンドで、insert 文を実行する


django アプリケーションで使用しているテーブルの全削除、再作成を実施したところ、
初期データとして必要なデータも消えてしまい、面倒なことになったので、
これを機に、初期データを投入する migrate ファイルを作成したので、
実施したことを記載します。


前提

環境情報は以下の通りです。

  • OS

    sw_vers
    -----------------------
    ProductName:    Mac OS X
    ProductVersion: 10.12.5
    BuildVersion:   16F73
    -----------------------
    

  • python version

    python3 -V
    -----------------------
    Python 3.5.1
    -----------------------
    

  • Django Version

    pip3 list | grep Django
    -----------------------
    Django (1.10.7)
    -----------------------
    


migrations.RunSQL にINSERT文を直書きする

以下の手順で実施しました。

  • 空のマイグレーションファイルを作成する

  • マイグレーションファイルに、migrations.RunSQL で、INSERT 文を記載する。

  • migrate 実行

空のマイグレーションファイルを作成する

./manage.py makemigrations festivals4partypeople --empty
-----------------------------------------
Migrations for 'festivals4partypeople':
  festivals4partypeople/migrations/0002_auto_20170604_1454.py:
-----------------------------------------

マイグレーションファイルに、migrations.RunSQL で、INSERT 文を記載する。

以下のようにSQL文を直に記載します。
第2引数のDELETE 文は、リカバリ用のSQLになります。

# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2017-06-04 05:54
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):
    dependencies = [
        ('festivals4partypeople', '0001_squashed_0003_auto_20170411_0110'),
    ]

    operations = [
        # echonest_artist UNKNOWN DATA
        migrations.RunSQL(
            """INSERT INTO echonest_artist (id, echonest_id, name, relate_status, create_date, update_date) VALUES (-1, 
            'XXXXXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXXXXX', '2', 
            '1970-01-01 00:00:00.000+09', '1970-01-01 00:00:00.000+09');""",
            """DELETE FROM echonest_artist where id = -1;"""),
        # lastfm_artist UNKNOWN DATA
        migrations.RunSQL(
            """INSERT INTO lastfm_artist (id, mbid, name, relate_status, create_date, update_date) VALUES (-1,
            'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXXXXXXXXXXXX', '2', '1970-01-01 00:00:00.000+09',
            '1970-01-01 00:00:00.000+09');""",
            """DELETE FROM lastfm_artist where id = -1;"""),
    ]

migrate 実行

./manage.py migrate
---------------------------------------------
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, festivals4partypeople, sessions
Running migrations:
  Applying festivals4partypeople.0002_auto_20170604_1454... OK
---------------------------------------------

migrations.RunSQL でSQLファイルを実行する

sqlparse をインストールする前提ですが、RunSQL で、外だしのsql ファイルが実行できるようです。
もともと投入データをSQL文で記載していましたので、結局こちらの方法で、初期データ投入用のスクリプトは作成しました。
以下、参考になりました。

sqlparse のインストール

python3 -m pip install sqlparse

マイグレーションファイルを作成する

  • migrationファイル

load_sql というメソッドを作成しました。
複数のINSERT文を記載したSQLファイルを文字列で読み込み、
RunSQLの引数とします。

# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2017-06-04 06:50
from __future__ import unicode_literals

from django.db import migrations


def load_sql(filename):
    f = open(filename)
    sql_statements = f.read()
    f.close()
    return sql_statements


class Migration(migrations.Migration):
    dependencies = [
        ('festivals4partypeople', '0002_auto_20170604_1454'),
    ]

    operations = [
        migrations.RunSQL(load_sql('festivals4partypeople/sqls/V1.0.0.1__Add_heldYears.sql')),
        migrations.RunSQL(load_sql('festivals4partypeople/sqls/V1.0.0.2__Add_festivals.sql')),
        migrations.RunSQL(load_sql('festivals4partypeople/sqls/V1.0.0.3__Add_artists.sql')),
    ]
  • sqlファイル

SQL ファイルの中身は以下のようなフォーマットです。
文末を;区切りにします。

INSERT INTO held_year (id, held_year, create_date, update_date) VALUES (nextval('held_year_id_seq'), '2010', current_date, current_date);
INSERT INTO held_year (id, held_year, create_date, update_date) VALUES (nextval('held_year_id_seq'), '2011', current_date, current_date);
INSERT INTO held_year (id, held_year, create_date, update_date) VALUES (nextval('held_year_id_seq'), '2012', current_date, current_date);
INSERT INTO held_year (id, held_year, create_date, update_date) VALUES (nextval('held_year_id_seq'), '2013', current_date, current_date);
INSERT INTO held_year (id, held_year, create_date, update_date) VALUES (nextval('held_year_id_seq'), '2014', current_date, current_date);
INSERT INTO held_year (id, held_year, create_date, update_date) VALUES (nextval('held_year_id_seq'), '2015', current_date, current_date);

migrate 実行

./manage.py migrate
---------------------------------------------
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, festivals4partypeople, sessions
Running migrations:
  Applying festivals4partypeople.0003_auto_20170604_1550... OK
---------------------------------------------

以上です。

コメント