Djangoであれこれとmodelをいじくってmigrationを繰り返していると、収拾がつかなくなって、最初からmigrationをやり直したい!!
と、なってしまうことがあります。
ここでは、migrationの履歴をリセットし、現在のmodelの内容を正として1からmigrationをやり直す手順を説明します。
環境構成
項目 | 内容 |
---|---|
Django | 2.2 |
DB | sqlite3(Django標準) |
アプリケーション | member_reg |
テーブル | member_reg_register |
1.modelを変更する。
「member_reg」はユーザー登録アプリケーションです。modelはRegisterとしています。
元々はPrimary key項目を設定していなかったのですが、新たに「user_id」という項目をPrimary keyとして追加します。
DjangoではPrimary keyを指定しないmodelは「id」という項目名でPrimary keyが自動で設定されています。
models.py(抜粋)
class Register(models.Model):
user_id = models.AutoField(primary_key=True)
family_name = models.CharField(max_length=50)
first_name = models.CharField(max_length=50)
family_name_k = models.CharField(max_length=50)
first_name_k = models.CharField(max_length=50)
mail = models.EmailField(max_length=100)
password = models.CharField(max_length=50)
tel1_1 = models.CharField(max_length=10)
tel1_2 = models.CharField(max_length=10)
tel1_3 = models.CharField(max_length=10)
tel2_1 = models.CharField(max_length=10)
tel2_2 = models.CharField(max_length=10)
tel2_3 = models.CharField(max_length=50)
gender = models.CharField(max_length=1)
birthday = models.DateField()
post_num = models.CharField(max_length=7)
prefecture = models.CharField(max_length=30)
city = models.CharField(max_length=100)
town = models.CharField(max_length=100)
banchi1 = models.CharField(max_length=5)
banchi2 = models.CharField(max_length=5)
banchi3 = models.CharField(max_length=5)
place = models.CharField(max_length=50)
2.mikemigrationの実行
user_idはnot null項目なので何か値を入れてくれとの警告がでます。ここではとりあえず0を設定します。
(django) C:\django\myprj>python manage.py makemigrations
You are trying to add a non-nullable field 'user_id' to register without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> 0
Migrations for 'member_reg':
member_reg\migrations\0009_auto_20200507_0050.py
- Remove field id from register
- Add field user_id to register
makemigration自体は動いていますが、failedで終わっています。
このままmigrateすると、以下のエラーになります。
django.db.utils.IntegrityError: UNIQUE constraint failed: new__member_reg_register.user_id
当然Primary keyの項目の値が重複してしまいます。
色々とやり方はあるようですが、過去のmigrationの履歴をリセットして新たにmigrationを開始してみます。
3.mikemigrationのリセット
まずは先ほどの状態からmakemigrationsします。
No changes detectedとなっていればOK.
(django) C:\django\myprj>python manage.py makemigrations
No changes detected
次にmigrationの履歴を確認します。
[X]はmigrate済、[ ]はmigrate未です。0009_auto_20200507_0050はmigrate出来ていません。
(django) C:\django\myprj>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
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
jsonsample
(no migrations)
member_reg
[X] 0001_initial
[X] 0002_auto_20200115_0051
[X] 0003_auto_20200119_1952
[X] 0004_auto_20200119_2039
[X] 0005_auto_20200119_2059
[X] 0006_auto_20200119_2245
[X] 0007_auto_20200123_0102
[X] 0008_auto_20200310_0013
[ ] 0009_auto_20200507_0050
modaltest
[X] 0001_initial
[X] 0002_auto_20200411_0956
sessions
[X] 0001_initial
–fake オプション、zeroオプションを指定して、擬似的にmigrationを削除します。
(django) C:\django\myprj>python manage.py migrate --fake member_reg zero
Operations to perform:
Unapply all migrations: member_reg
Running migrations:
Rendering model states... DONE
Unapplying member_reg.0008_auto_20200310_0013... FAKED
Unapplying member_reg.0007_auto_20200123_0102... FAKED
Unapplying member_reg.0006_auto_20200119_2245... FAKED
Unapplying member_reg.0005_auto_20200119_2059... FAKED
Unapplying member_reg.0004_auto_20200119_2039... FAKED
Unapplying member_reg.0003_auto_20200119_1952... FAKED
Unapplying member_reg.0002_auto_20200115_0051... FAKED
Unapplying member_reg.0001_initial... FAKED
ここでもう一度showmigrationsします。
member_regに関するmigrationの履歴が全て削除されています。
(django) C:\django\myprj>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
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
jsonsample
(no migrations)
member_reg
[ ] 0001_initial
[ ] 0002_auto_20200115_0051
[ ] 0003_auto_20200119_1952
[ ] 0004_auto_20200119_2039
[ ] 0005_auto_20200119_2059
[ ] 0006_auto_20200119_2245
[ ] 0007_auto_20200123_0102
[ ] 0008_auto_20200310_0013
[ ] 0009_auto_20200507_0050
modaltest
[X] 0001_initial
[X] 0002_auto_20200411_0956
sessions
[X] 0001_initial
migrationsファイルを削除します。
migrationsは以下のフォルダから「__ init__.py」を除く全てのファイルを削除します。
サブフォルダもすべて対象です。
残るのはこれだけになるはずです。
__pycache__
__init__.py
ここでもう一度showmigrationsを実行します。
(django) C:\django\myprj>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
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
jsonsample
(no migrations)
member_reg
(no migrations)
modaltest
[X] 0001_initial
[X] 0002_auto_20200411_0956
sessions
[X] 0001_initial
member_reは「(no migrations)」になっています。
4.mikemigrationの再実行
過去のmigration履歴は削除できましたので、ここからが新規のmigrationです。
(django) C:\django\myprj>python manage.py makemigrations
Migrations for 'member_reg':
member_reg\migrations\0001_initial.py
- Create model Register
makemigrationはうまくいきました。
(django) C:\django\myprj>python manage.py migrate
django.db.utils.OperationalError: table "member_reg_register" already exists
migrateは実テーブルがすでに存在するので怒られてしまいます。
データベースを削除します。sqlite3なのでコマンドで削除していきます。
(django) C:\django\myprj> python manage.py dbshell
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups member_reg_register
auth_user_user_permissions modaltest_condition
sqlite>
DROP文を発行して、テーブルを削除します。
sqlite> drop table member_reg_register;
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups modaltest_condition
auth_user_user_permissions
sqlite>
この状態でもう一度migrationにトライしてみます。
(django) C:\django\myprj> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, member_reg, modaltest, sessions
Running migrations:
Applying member_reg.0001_initial... OK
成功しました。
migrationの結果を見てみます。
「member_reg」は「 [X] 0001_initial」の1回のみです。
(django) C:\django\myprj> 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
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
jsonsample
(no migrations)
member_reg
[X] 0001_initial
modaltest
[X] 0001_initial
[X] 0002_auto_20200411_0956
sessions
[X] 0001_initial
テーブルも確認できます。
(django) C:\django\myprj>python manage.py dbshell
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups member_reg_register
auth_user_user_permissions modaltest_condition
user_idがprimary keyになっています。
sqlite> .schema member_reg_register
CREATE TABLE IF NOT EXISTS "member_reg_register" (
"user_id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"family_name" varchar(50) NOT NULL,
"first_name" varchar(50) NOT NULL,
"family_name_k" varchar(50) NOT NULL,
"first_name_k" varchar(50) NOT NULL,
"mail" varchar(100) NOT NULL,
"password" varchar(50) NOT NULL,
"tel1_1" varchar(10) NOT NULL,
"tel1_2" varchar(10) NOT NULL,
"tel1_3" varchar(10) NOT NULL,
"tel2_1" varchar(10) NOT NULL,
"tel2_2" varchar(10) NOT NULL,
"tel2_3" varchar(50)NOT NULL,
"gender" varchar(1) NOT NULL,
"birthday" date NOT NULL,
"post_num" varchar(7) NOT NULL,
"prefecture" varchar(30) NOT NULL,
"city" varchar(100) NOT NULL,
"town" varchar(100) NOT NULL,
"banchi1" varchar(5) NOT NULL,
"banchi2" varchar(5) NOT NULL,
"banchi3" varchar(5) NOT NULL,
"place" varchar(50) NOT NULL);
sqlite>