VPS 移行をして、Django dumpdata loaddata を使ってデータ移行を行いました。
過去のマイグレーション失敗や、そもそも除外しないと移行できない部分があって結構ハマりましたので、備忘としてやったことを記載します。
前提
移行前、移行後の環境について情報を記載します。
移行前
-
OS の Version
CentOS 6.9
-
Django の Version
Django 1.10.8
-
Python の Version
python 2.7.6
移行後
-
OS の Version
CentOS Linux release 7.4.1708 (Core)
-
Django の Version
Django 1.10.8
-
Python の Version
Python 3.6.4
データ移行の手順 (初回)
以下の手順で実施しました。
1. 移行前環境で、daupdata を実行
python2.7 manage.py dumpdata > dump.json
python3.6 manage.py flush
python3.6 manage.py loaddata dump.json
発生したトラブル
キー重複エラー1
全てのデータを投入したところ、以下のエラーが発生しました。
django.db.utils.IntegrityError: Problem installing fixture '/xxxx/dump.json': Could not load contenttypes.ContentType(pk=1): duplicate key value violates unique constraint "django_content_type_app_label_76bd3d3b_uniq"
DETAIL: Key (app_label, model)=(auth, permission) already exists.
DjangoをsqliteからPostgreSQLに切り替えた(dumpdata/loaddata) - [Dd]enzow(ill)? with DB and Python
- 修正後のdumpdata
python manage.py dumpdata --exclude auth.permission --exclude contenttypes > dump.json
RelatedObjectDoesNotExist
修正した dumpdata コマンドを実行したところ以下のエラーが発生しました。
django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist: Problem installing fixture 'xxxx/dump.json': Comment has no content_type.
showmigrations
で、Migration の状況を見る限り、移行前、移行後の環境の適用状況は同じでしたが、DBのテーブル構造は確かに違うという状況でした。 原因はわからずですが、Comment のデータは削除済データで不要だったため、移行前の環境から、Comment関連のデータを削除しました。
- コメント関連のデータを削除
Comment 関連のテーブルは3テーブルあり、3テーブルのデータを物理削除しました。
delete from django_comment_flags; delete from generic_threadedcomment; delete from django_comments;
violates foreign key constraint “django_admin_content_type_id_c4bce8eb_fk_django_content_type_id”
Comment データ削除後、以下のエラーが発生しました。
return self.cursor.execute(sql)
django.db.utils.IntegrityError: Problem installing fixtures: insert or update on table "django_admin_log" violates foreign key constraint "django_admin_content_type_id_c4bce8eb_fk_django_content_type_id"
DETAIL: Key (content_type_id)=(43) is not present in table "django_content_type".
django_admin_log
は、ADMIN での 操作履歴が格納されるテーブルです。どの Model に対して操作したのか django_content_type
と関連づいたデータが設定されるようです。 前述の原因不明のMigration の 差分が影響しているようで、移行前環境の
django_content_type
と、移行後環境のdjango_content_type
のデータが異なったため、admin のデータも除外しました。
python2.7 manage.py dumpdata --exclude admin --exclude auth.permission --exclude contenttypes > dump.json
format を 変更して dumpdata を試した
作業途中で、format を xml にして、dumpdata を実行したのですが、シリアライズできない文字列がありエラーが発生しました。
-
format xml の dumpdata コマンド
python3 manage.py dumpdata --format=xml > django_dump.xml
-
エラー
CommandError: Unable to serialize database: BlogPost.description (pk:6) contains unserializable characters
以下のようなスクリプトを書いて、対象のデータを特定しましたが、対象 Blog 記事には確かにシリアライズできなそうな文字が含まれており、削除したところ、dumpできました。
- スクリプト
import codecs from mezzanine.blog.models import BlogPost from django.core import serializers for blog_post in BlogPost.objects.all(): print("###################") print(blog_post) data = serializers.serialize("xml", BlogPost.objects.all()) print(data)
データ移行の手順 (トラブル解消後)
トラブル解消後の手順は以下になります。
1. 移行前環境で、daupdata を実行
python2.7 manage.py dumpdata --exclude admin --exclude auth.permission --exclude contenttypes > dump.json
python3.6 manage.py flush
python3.6 manage.py loaddata dump.json
以上です。
コメント