web-dev-qa-db-ja.com

Django複数のデータベースでの移行

データ移行の作成に苦労しています。アプリには2つのデータベースを使用しています。 settings.pyでデータベースを構成し、Django docs のようなルーターも作成しました。

# settings.py
DB_Host = 'localhost'
DATABASES = {
'default': {
    'ENGINE': 'Django.db.backends.mysql',
    'NAME': 'helios',
    'Host': DB_Host,
    'OPTIONS': {
        'read_default_file': join(dirname(__file__), 'default.cnf'),
    },
},
'other': {
    'ENGINE': 'Django.db.backends.mysql',
    'NAME': 'gala_pol',
    'Host': DB_Host,
    'OPTIONS': {
        'read_default_file': join(dirname(__file__), 'other.cnf'),
    },
},

DATABASE_APPS_MAPPING = {
    'contenttypes': 'default',
    'auth': 'default',
    'admin': 'default',
    'sessions': 'default',
    'messages': 'default',
    'staticfiles': 'default',
    'woodsmen': 'default',
    'helios': 'default',
    'hush': 'default',
    'hunt': 'other',
    'meat': 'other',
    'beast': 'other',
}

# routers.py

class DatabaseAppsRouter(object):

    def db_for_read(self, model, **hints):

        if model._meta.app_label in settings.DATABASE_APPS_MAPPING:
            return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
        return None

    def db_for_write(self, model, **hints):

        if model._meta.app_label in settings.
            return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
        return None

    def allow_relation(self, obj1, obj2, **hints):

        db1 = settings.DATABASE_APPS_MAPPING.get(obj1._meta.app_label)
        db2 = settings.DATABASE_APPS_MAPPING.get(obj2._meta.app_label)
        if db1 and db2:
            return db1 == db2
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):

        if db in settings.DATABASE_APPS_MAPPING.values():
            return settings.DATABASE_APPS_MAPPING.get(app_label) == db
    Elif app_label in settings.DATABASE_APPS_MAPPING:
            return False

これらのアプリの1つのモデルと移行を次に示します。

# hunt.models.py

class Dish(models.Model):
    """
    Investigation case
    """
    display_name = models.CharField(max_length=64, unique=True)
    department = models.ForeignKey(Kitchen, null=True)
    case_type = models.PositiveSmallIntegerField(choices=CASE_TYPE_CHOICES, default=DEF_CASE_TYPE)
    created_at = models.DateTimeField(blank=True, null=True)
    comment = models.CharField(max_length=256, blank=True, null=True)

    class Meta:
        verbose_name = 'case'
        app_label = 'hunt'

    def __unicode__(self):
        return (u'%s (%s)' % (self.display_name, self.created_at)).strip()


# hunt.migrations.0001_initial.py

class Migration(migrations.Migration):

    app_label = 'hunt'

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Dish',
            fields=[
                ('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
                ('display_name', models.CharField(max_length=64, unique=True)),
                ('case_type', models.PositiveSmallIntegerField(default=0, choices=[(0, 'Unknown'), (1, 'General'), (2, 'Terror'), (3, 'Narco'), (4, 'Fraud'), (5, 'Slavery'), (6, 'Traffic'), (7, 'RICO'), (8, 'War'), (9, 'Cyber'), (20, 'Other')])),
                ('created_at', models.DateTimeField(null=True, blank=True)),
                ('comment', models.CharField(max_length=256, null=True, blank=True)),
            ],
            options={
                'verbose_name': 'case',
            },
        ),
    ]

# hunt.migrations.0002_add_hunts.py


def create_initial_hunts(apps, schema_editor):

    if settings.DEBUG:    
        print('\nContent added')


class Migration(migrations.Migration):
    dependencies = [
        ('hunt', '0001_initial'),
    ]


    operations = [
        migrations.RunPython(create_initial_hunts, hints={'schema_editor': 'other'}),
    ]

問題は、「migrate」コマンドを実行すると、デフォルトのデータベースに接続されているアプリケーションのみが移行されることです。残りのアプリの移行は決して実行されません。 --databaseオプションを使用してそのようなアプリの移行を起動すると、正常に機能します。

移行ごとにデータベースを指定するにはどうすればよいですか?ルータはこれを正確に管理することになっているのではないですか?それとも何か他のものを逃したのですか?

18
Leon Kladnitsky

_--database_でターゲットを指定して、データベースごとにmigrateを1回実行する必要があります。ルーターを調べて、そのデータベースで実際に実行する移行を確認します。

私はそれが暗黙よりも明示を優先するようにこのように設計されたと思います。たとえば、ワークフローでは、異なるデータベースを異なるタイミングで移行する必要がある場合があります。

ただし、実際に実行された移行を出力から確認することはできません since

allow_migrate()Falseを返す場合、migratedbで実行すると、_model_name_の移行操作は何も通知されずにスキップされます。