Python Django 入門トップページ


Django のマイグレーション

  1. 概要と準備
  2. マイグレーションの実行
  3. モデルの作成とマイグレーション
  4. テーブルに列を追加
  5. テストデータの投入
  6. ロールバックとテーブルの再生成
  7. テーブルに再び列を追加

Django のマイグレーション

テーブルに列を追加

これまでのステップで comments_comment テーブルには id, title, created_at の列が定義されました.次にこのテーブルに body 列を追加すること考えます.

テーブルに列を追加するためには,models.py を編集して定義を追加することになります.このとき,default に何らかの値を指定しなければならないことに注意してください.

from django.db import models

# Create your models here.

class Comment(models.Model):
    title = models.CharField(max_length=200)
    body = models.CharField(max_length=1000, default="")
    created_at = models.DateTimeField(auto_now_add=True)

モデルの編集ができたらマイグレーションファイルを生成します.

(py39) C:\Users\lecture\Documents\django\django_comment>python manage.py makemigrations comments ⏎
Migrations for 'comments':
  comments\migrations\0002_comment_body.py
    - Add field body to comment

(py39) C:\Users\lecture\Documents\django\django_comment>

作成されたマイグレーションファイル (0002_comment_body.py) の中身を確認すると,テーブルの生成ではなく,列を追加 (AddField) するコードになっていること,前のページでは CreateModel になっていたことに注意してください.

comments/migrations/0002_comment_body.py# Generated by Django 4.0.6 on 2022-08-01 18:21

from django.db import migrations, models


class Migration(migrations.Migration):

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

    operations = [
        migrations.AddField(
            model_name='comment',
            name='body',
            field=models.CharField(default='', max_length=1000),
        ),
    ]

もちろんマイグレーションを実行していないので,まだこの段階ではテーブルに列は追加されていません.

sqlite> .schema comments_comment ⏎
CREATE TABLE IF NOT EXISTS "comments_comment" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
    "title" varchar(200) NOT NULL,
    "created_at" datetime NOT NULL
);
sqlite>

showmigrations コマンドの結果も予想通りのはずです.

(py39) C:\Users\lecture\Documents\django\django_comment>python manage.py showmigrations ⏎
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
 [X] 0008_alter_user_username_max_length
 [X] 0009_alter_user_last_name_max_length
 [X] 0010_alter_group_name_max_length
 [X] 0011_update_proxy_permissions
 [X] 0012_alter_user_first_name_max_length
comments
 [X] 0001_initial
 [ ] 0002_comment_body
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
sessions
 [X] 0001_initial

(py39) C:\Users\lecture\Documents\django\django_comment>

ここでマイグレーションを実行して,テーブルに列を追加します.

(py39) C:\Users\lecture\Documents\django\django_comment>python manage.py migrate ⏎
Operations to perform:
  Apply all migrations: admin, auth, comments, contenttypes, sessions
Running migrations:
  Applying comments.0002_comment_body... OK

(py39) C:\Users\lecture\Documents\django\django_comment>

実行状況を確認します.

(py39) C:\Users\lecture\Documents\django\django_comment>python manage.py showmigrations ⏎
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
 [X] 0008_alter_user_username_max_length
 [X] 0009_alter_user_last_name_max_length
 [X] 0010_alter_group_name_max_length
 [X] 0011_update_proxy_permissions
 [X] 0012_alter_user_first_name_max_length
comments
 [X] 0001_initial
 [X] 0002_comment_body
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
sessions
 [X] 0001_initial

(py39) C:\Users\lecture\Documents\django\django_comment>

データベースのテーブルに列が追加されていることが確認できました.

sqlite> .schema comments_comment ⏎
CREATE TABLE IF NOT EXISTS "comments_comment" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
    "title" varchar(200) NOT NULL,
    "created_at" datetime NOT NULL,
    "body" varchar(1000) NOT NULL
);
sqlite>

目次に戻る