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を指定し、管理対象外にしておく必要がある
- 意図せず対象のデータベースに