投稿日:2021年6月16日
この記事ではDjangoコマンドを使ったダンプファイルの作成・読み込みの方法などについて詳しく解説しています。
Web開発で、アプリケーションの初期データやバックアップのためにダンプ作成は必須の知識です。実ははDjangoにはデフォルトこれを行うためのコマンドが用意されています。
この記事ではDjangoコマンドを使ったダンプファイルの作成・読み込みの方法などについて詳しく解説しています。
この記事は以下の環境で確認されました。
django-adminとmanage.pyにはdumpdataというコマンドが用意されています。そのコマンドを使うことで簡単にDjango用のDBダンプファイルを作成することができます。
dumpdataコマンドはデフォルトで全てのデータをjson形式で出力できます。出力ファイル名は-oオプションで指定しましょう。
$ python manage.py dumpdata -o dump.json
出力ファイルは以下のようになっています。
[
{
"model": "contenttypes.contenttype",
"pk": 1,
"fields": {
"app_label": "admin",
"model": "logentry"
}
},
// [...]
{
"model": "schedules.schedule",
"pk": 1,
"fields": {
"title": "myschedule"
}
},
{
"model": "schedules.task",
"pk": 1,
"fields": {
"schedule": 1,
"user": 1,
"title": "sample task",
"content": "asdfasdfasdf",
"start_time": "2021-06-15T02:39:19Z",
"end_time": "2021-06-15T02:39:22Z"
}
},
{
"model": "schedules.task",
"pk": 2,
"fields": {
"schedule": 1,
"user": 1,
"title": "kkk",
"content": "\"dfasdfasfd\"",
"start_time": "2021-06-15T02:39:43Z",
"end_time": "2021-06-15T02:39:49Z"
}
},
]
特定のテーブルのみのダンプをとることもできます。コマンドの引数にapp名を渡すことで、対象app内の全てのテーブルをダンプします。またapp名.テーブル名を渡すことで特定のテーブルのみをダンプすることができます。
$ python manage.py dumpdata schedules
$ python manage.py dumpdata schedules.Task
引数は複数指定できるため、複数のapp、テーブルをダンプすることもできます。
$ python manage.py dumpdata -o dump.json schedules accounts
$ python manage.py dumpdata -o dump.json schedules.Task schedules.Schedule
その他の使い方については公式ドキュメントを参照してください。
出力されるダンプデータは以下のようなオブジェクトの配列になっています。
django-adminとmanage.pyにはloaddataというコマンドも用意されています。loaddumpはダンプデータをDBにインサートすることができます。
loaddataには引数としてダンプファイルを指定します。
$ python manage.py loaddata dump.json
ダンプファイルは以下の順に探しに行きます。
読み込むデータについては--excludeで除外するappのラベルを指定することができます。例えば、一部テーブルは他のリソースから読み込みたい場合などは対象テーブルだけ除外しておくといいでしょう。
$ python manage.py loaddata --exclude schedules dump.json
その他の使い方については公式ドキュメントを参照してください。
同じプライマリーキーのレコードがすでにDBに存在したとしても、コマンドは正常に終了します。普段DBのdumpコマンドを利用している人にとっては、これは奇妙に見えるかもしれません。
実はloaddataコマンドは対象テーブルを一旦すべて取得してきて、対象jsonと比較した後、再度データを入れ直しているのです。
読み込むデータは必ずしもdumpdataコマンドで生成したjsonである必要はありませんが、Djangoのシリアライズサポートを満たしている形式である必要があります。
json以外の形式を読み込む場合には--formatオプションで形式を指定しましょう。
$ python manage.py loaddata --format xml dump.xml
またダンプファイルがzip, gz, bz2, lzma, xzで圧縮してある場合でも、そのまま読み込むことができます。
便利〜!!!
$ python manage.py loaddata dump.json
ほとんどのRDMSはデータをダンプする方法を既に提供しています。
それなのにDjangoのコマンドでする意味はあるのでしょうか?
そこで、ここではDjangoコマンドを使う場合のメリット・デメリットについて解説します。
Djangoコマンドの大きなメリットは2つあります。
1つ目はDjangoによって、使用データベースの差異を吸収できる点です。
では例を元にアプローチを見てみましょう。
Djangoアプリケーションではじめのうちはmysqlデータベースを使っていたとします。その後改修を重ねていく中でpostgresqlのみの機能を使いたくなり、データベースを変更することになりました。そのような場合でもDjangoコマンドなら簡単に以降できます。
まずは設定ファイルは以下のようになっているとします。
# [...]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': ‘<db_name>’,
'USER': '<db_username>',
'PASSWORD': '<password>',
'HOST': '<db_hostname_or_ip>',
'PORT': '<db_port>',
}
}
# [...]
ここでサービスを一旦止めて、現在のデータのダンプを作成します。
$ python manage.py dumpdata dump.json
次のデータベースのライブラリをインストールします。
$ pip install psycopg2
ここで設定ファイルを書き換えます。
# [...]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': ‘<db_name>’,
'USER': '<db_username>',
'PASSWORD': '<password>',
'HOST': '<db_hostname_or_ip>',
'PORT': '<db_port>',
}
}
# [...]
後はもとのデータベースを反映させれば移行は完了です。
$ python manage.py migrate # テーブル定義の反映
$ python manage.py loaddata dump.json # データの反映
簡単ですね!
使うDBによってクライアントライブラリと設定ファイルは違うものの基本的にすべて同じやり方で移行することができます。簡単な方法を使ってDBの移行ができることは非常に大きなメリットであると言えるでしょう。
基本的にdumpdateでとったデータはDjangoでしか使用できません。
理由は、以下のようにダンプデータの形式がDjangoのModelに依存しているためです。
結論から言うと、Djangoを使うことが決定しているのであれば基本的にはDjangoコマンドを使うほうが楽だと思います。