logo サブスレッド

Django の makemigrations で作成したファイルを微調整する

月曜日担当の鳥飼です。
お久しぶりです。よろしくお願いします。

Django使っていますか? 私はまだまだお世話になっています。Django便利。
Djangoの便利な機能として、モデルに変更があればマイグレーションの形で保存し、DBに変更を反映できる便利な機能があります。
基本的には、この生成されたマイグレーションファイルをそのまま使うのですが、+αの対応を入れたい場合があります。
そんな時はマイグレーションファイルをちょっと調整するだけで解決できるかもしれませんよ(・ω・)ノ

今回は、その調整例をご紹介。

追加した列に対して、既存のデータに合わせて初期値を設定したい

こんなマイグレーションファイルが生成されたとしまして…

# -*- coding: utf-8 -*-
# Generated by Django 1.11.7 on 2018-06-04 09:47
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('app', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='Hoge',
            name='code',
            field=models.CharField(default=None, max_length=20, null=True, verbose_name='hoge識別コード'),
        ),
    ]

例えば、既存データに対して、

  • id < 100 の場合の初期値はhoge
  • 100 <= id < 200 の場合の初期値はhige
  • それ以外はhage

…としたいな、という場合。
SQLやコマンドを別途用意するのも良いのですが、マイグレーションファイルを以下のように調整しても良いんです。

# -*- coding: utf-8 -*-
# Generated by Django 1.11.7 on 2018-06-04 09:47
from __future__ import unicode_literals

from django.db import migrations, models


# 追加
def initialize(apps, schema_editor):
    # 第一引数はアプリ名、第二引数はモデル名を指定
    Hoge = apps.get_model('app', 'Hoge')

    # migrate 時に実行したい処理を記述
    for hoge in Hoge.objects.all():
        hoge.code = 'hage'
        if hoge.id < 100:
            hoge.code = 'hoge'
        if 100 <= hoge.id < 200:
            hoge.code = 'hige'
        hoge.save()


class Migration(migrations.Migration):

    dependencies = [
        ('app', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='Hoge',
            name='code',
            field=models.CharField(default=None, max_length=20, null=True, verbose_name='hoge識別コード'),
        ),
        migrations.RunPython(initialize)  # 追加
    ]

このマイグレーションファイルをmigrateすると、initialize()の処理が実行され、codeに値がセットされます。

上記のコードの場合だと、code列を追加した後に初期値を更新する処理が実行されます。
もちろん、migrations.AddFieldより前にmigrations.RunPython()を指定することもできます(・ω・)ノ

これで何が嬉しいか

「このマイグレーションを実行した後は、コレコレこういうSQLを実行してください」とか
「このショットのコマンドを実行してください」とか
「リリース作業時にはmigrateとは別に別途このような作業が必要」とか
そういう 「後々コケるので、やる必要がある作業」 が不要になるということです。ブラボー。
migrateすればよろしくやってくれるという訳なので、意識しなければならないことが減って気持ち的にもヘルシーですね。

今日のひとネタでした(・ω・)ノ

現在の位置:サブスレッド ホーム > 技術ブログ > Django の makemigrations で作成したファイルを微調整する