【Django】dumpdata&loaddataコマンドでデータを他のSQL(SQLite3・MySQL・PostgreSQL・...)へ移動


投稿日 2020年9月1日 >> 更新日 2024年7月7日

今回は、Djangoの管理タスク用コマンドの「dumpdata」と「loaddata」を使用して、既存のデータベース内に保存されているデータを他のSQL(SQLite3・MySQL・PostgreSQL・...)へ移動、もしくわ移行していきたいと思います。

よくありそうなことで、DjangoではデフォルトでSQLite3を使用できることから、MySQLなどの大規模なデータベースを設定するタイミングを逃し、そのまま小規模なSQLite3を使用していることが多々あるかと思います。

他にも、特定のモデルに保存されているデータを他のアプリのデータベースに移動させるといった事です。

ここではSQLite3からMySQLのデータベースへデータを移動させる例を詳しく行っていきますが、PostgreSQLも同じような要領で移動、もしくわ移行・切り替えができるのでぜひ試してみて下さい。

実行環境&使用ライブラリ

実行環境
Windows Subsystem for Linux
Python3.6.9
pip 9.0.1
使用ライブラリ ライセンス
Django==3.1 BSD
mysqlclient==2.0.1(MySQLのドライバ) GNU General Public License (GPL)
psycopg2-binary==2.8.5(PostgreSQLのドライバ) GNU Library or Lesser General Public License (LGPL)

準備

それぞれ使用先のSQLドライバをインストールします。

# MySQLのドライバ
$ pip install mysqlclient

or

# PostgreSQLのドライバ
$ pip install psycopg2-binary

前提としているモデルフィールド

「models.py」では以下のような設定となっています。

# app/models

from django.db import models


class Todo(models.Model):
    title = models.CharField(max_length=50)
    created_at = models.DateField(auto_now_add=True)

    def __str__(self):
        return self.title

データベースの作成(MySQL)

ここでは「SQLite3」→「MySQL」へ切り替えてデータを移動させるといった流れとするので、先にMySQLを起動してデータベースを作成しておきます。

$ mysql -u root -p
mysql> # データベースの一覧を取得
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+

mysql> # データベース「testdb」を作成
mysql> create database testdb;
Query OK, 1 row affected (0.03 sec)

mysql> # もう1度データベースの一覧を取得
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| testdb             |
+--------------------+

mysql> quit

後ほど作成した「testdb」をDjangoの設定ファイル記述します。

dumpdataコマンド

dumpdataコマンドでは、データの出力と合わせて幾つかオプションを使用することができます。

Djangoの公式ドキュメントで詳しく載っています。

Django公式ドキュメント --dumpdata

SQLite3に保存されているデータの出力

まずはdumpdataコマンドを使用して、保存されているデータを出力してみます。

$ python3 manage.py dumpdata
[{"model": "auth.permission", "pk": 1, "fields": {"name": "Can add log entry",.....]

このように辞書形式となっていて、横一行となってデータベースに保存されているデータが出力されます。

特定のモデルを指定してデータの出力

dumpdataコマンドの引数にアプリ名やモデル名を与えると、そのモデル内に保存されているデータだけを出力することができます。

引数を指定しなければデータベース内のデータ全て取得

$ python3 manage.py dumpdata

引数にアプリ名を与えるとアプリ内に保存されているデータを取得

$ python3 manage.py dumpdata app

引数にアプリ内のモデル名を与えるとモデルに限られたデータを取得

$ python3 manage.py dumpdata app.todo

出力されるデータに改行(インデント)を付ける

出力されるデータが一行では少し見難いこともあるので、オプションに改行(インデント)と改行の数を指定して中身を見やすくします。

$ python3 manage.py dumpdata app.Todo --indent 1
[
{
 "model": "app.todo",
 "pk": 1,
 "fields": {
  "title": "test1",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 2,
 "fields": {
  "title": "test2",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 3,
 "fields": {
  "title": "test3",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 4,
 "fields": {
  "title": "test4",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 5,
 "fields": {
  "title": "test5",
  "created_at": "2020-09-01"
 }
}
]

5つのTodoリストが保存されていることが分かります。

管理者のテーブルも確認してみます。

$ python3 manage.py dumpdata auth.user --indent 1
[
{
 "model": "auth.user",
 "pk": 1,
 "fields": {
  "password": "********",
  "last_login": null,
  "is_superuser": true,
  "username": "admin",
  "first_name": "",
  "last_name": "",
  "email": "admin@sample.com",
  "is_staff": true,
  "is_active": true,
  "date_joined": "2020-09-01T03:25:07.308Z",
  "groups": [],
  "user_permissions": []
 }
}
]

管理者もしっかり登録されています。

データをファイルへ書き込み

SQLiteに保存されているデータを確認することが出来たので、デフォルトのフォーマット形式である「json」ファイルに書き込んでいきたいと思います。

書き込むファイル名は、「db_chenge.json」として作成します。

$ python3 manage.py dumpdata > db_chenge.json

そうするとカレントディレクトリにファイルがあることが確認できます。

$ ls
app  config  db.sqlite3  db_chenge.json  manage.py

データベースの切り替え(SQLite3からMySQL)

さきほど作成したMySQLのデータベースを設定するために、設定ファイル「settings.py」を編集します。

# config/settings.py

...

""" SQLite3
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
"""

# MySQL
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testdb',  # db名
        'USER': 'root',
        'PASSWORD': 'パスワード',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

設定したら、マイグレーションを実行します。

$ python3 manage.py migrate

これでMySQLへと置き換わったデータベースのテーブルが作成されたので、先ほど書き込んだjsonファイルを読み込ませるだけです。

loaddataコマンド

Django公式ドキュメント --loaddata

loaddataコマンドを使用することで、jsonファイルに書き込んだデータを読み込む事ができます。

$ python3 manage.py loaddata db_chenge.json
Installed 41 object(s) from 1 fixture(s)

db_chenge.jsonにはデータベースに保存されたデータが書き込まれていますが、「app.todo」のようにモデルが指定されたデータが書き込まれている場合は以下のようにオプションを指定することができます。

loaddataコマンドの「--app」オプションにアプリ名とモデル名を指定します。

$ python3 manage.py loaddata --app app.todo db_chenge.json

これだけで、データベース間でのデータの移動をすることができました。

実際にデータが保存されているか「dumpdata」コマンドで確認していきます。

まずは管理者が登録されているか確認

$ python3 manage.py dumpdata auth.user --indent 1
[
{
 "model": "auth.user",
 "pk": 1,
 "fields": {
  "password": "******",
  "last_login": null,
  "is_superuser": true,
  "username": "admin",
  "first_name": "",
  "last_name": "",
  "email": "admin@sample.com",
  "is_staff": true,
  "is_active": true,
  "date_joined": "2020-09-01T03:25:07.308Z",
  "groups": [],
  "user_permissions": []
 }
}
]

Todoモデルのデータが保存されているか確認

$ python3 manage.py dumpdata app.Todo --indent 1
[
{
 "model": "app.todo",
 "pk": 1,
 "fields": {
  "title": "test1",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 2,
 "fields": {
  "title": "test2",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 3,
 "fields": {
  "title": "test3",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 4,
 "fields": {
  "title": "test4",
  "created_at": "2020-09-01"
 }
},
{
 "model": "app.todo",
 "pk": 5,
 "fields": {
  "title": "test5",
  "created_at": "2020-09-01"
 }
}
]

しっかりデータは移動されているようですが、気になる方はサーバーを起動して管理画面を確認することをお勧めします。

特定のモデル内のデータを移動させたい場合は、jsonファイルに書き込む際にオプション指定することでデータを取り出すことができるので非常に便利ですね。

それでは以上となります。

最後までご覧いただきありがとうございました。