Миграции Django с несколькими базами данных

Мне сложно создавать миграцию данных. Я использую две базы данных для своих приложений. Я настроил базы данных в 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

Вот модель и миграция одного из этих приложений:

# 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 - он отлично работает.

Как я могу указать базу данных для каждой миграции? Разве маршрутизатор не должен справляться именно с этим? Или я пропустил что-то еще?

Ответ 1

Вы должны запустить migrate один раз для каждой базы данных, указав цель с помощью --database. Каждый раз он будет консультироваться с вашим маршрутизатором, чтобы увидеть, какие миграции на самом деле выполнять в этой базе данных.

Я предполагаю, что это было разработано таким образом, чтобы способствовать явности по сравнению с неявностью. Например, для вашего рабочего процесса может потребоваться перенести разные базы данных в разное время.

Однако обратите внимание, что по выходным данным вы не сможете определить, какие миграции были действительно выполнены, с момента:

Если allow_migrate() возвращает False, любые операции миграции для model_name будут автоматически пропущены при запуске migrate на db.