Djangoフレームワークでは、データベースルータークラスを作成して、 settings.DATABASE_ROUTERS
に設定することで、モデル毎に使用するデータベースを変えたりできます。
データベースルーターにはいくつかのメソッドを実装しますが、その中の一つ、 allow_migrate
を実装した際のマイグレーション処理の挙動について気になったので調べました。
試した環境は、Python3.7.1、Django 2.1.3。
前提
- Djangoのプロジェクト名: project1
- アプリケーション名: myapp
対象のモデルは以下の通り:
myapp/models.py
:
from django.db import models class Spam(models.Model): name = models.CharField(max_length=20)
この Spam
モデルをデータベースルーターにて、マイグレーションの対象外とします。
データベースルーターは以下の通り:
project1/db_router.py
:
class DatabaseRouter: def allow_migrate(self, db, app_label, model_name=None, **hints): if app_label == 'myapp': return False return None
settings.py
の DATABASE_ROUTERS
に設定しています。
project1/settings.py
(抜粋):
DATABASE_ROUTERS = [
'project1.db_router.DatabaseRouter',
]
makemigrationsを実行した場合
マイグレーションファイルを作成する makemigrations
コマンドを実行した場合は、 allow_migrate
で False
を返却しても、マイグレーションファイルは作成されます。
$ python manage.py makemigrations myapp Migrations for 'myapp': myapp/migrations/0001_initial.py - Create model Spam
migrateを実行した場合
マイグレーションファイルを作成した状態で、マイグレーションを実行する migrate
コマンドを実行した場合は、対象のマイグレーションはスキップされます。
$ python manage.py showmigrations myapp myapp [ ] 0001_initial $ python manage.py migrate myapp Operations to perform: Apply all migrations: myapp Running migrations: Applying myapp.0001_initial... OK $ python manage.py showmigrations myapp myapp [X] 0001_initial
このとき、Djangoのマイグレーションの管理情報を格納するテーブルには、マイグレーションの実行済みを表すレコードが作成されます。
$ sqlite3 db.sqlite3 -line "select * from django_migrations" id = 1 app = myapp name = 0001_initial applied = 2018-11-20 20:59:28.637569
注意したい点
allow_migrate
でFalse
を返しても、migrate
ではマイグレーションファイルがあればマイグレーションの管理テーブルには書き込まれる- 意図せず対象のデータベースに
django_migrations
データベースが作成されたり、レコードが書き込まれることがある - 管理情報を書き込みたくない場合は、モデルに
Meta.managed = False
を指定し、管理対象外にしておく必要がある
- 意図せず対象のデータベースに