Django迁移了具有多个应用程序的多个数据库

时间:2019-11-26 18:32:26

标签: django django-models django-migrations

我有一个django项目,其中包含2个应用程序,每个应用程序都在不同的DB上运行(我们称它们为default和DB2)。 我已经创建了一个路由器来管理数据,并将该路由器添加到我的settings.py

运行迁移时,我得到Applying analytics.0001_initial... OK,但是在默认数据库中,唯一要更新的是django_migrations表,该表显示应用程序分析已使用0001进行了迁移,而在DB2中,该表甚至根本没有创建。

转到Django shell并尝试做obj.objects.all()给我表DB2.table_name不存在 我还验证了sql DB2中存在的内容,但没有我创建的表

我的路由器:

class DB2Router(object):
    """
    A router for apps that connect directly to the DB2 database.

    This router allows apps to directly update the DB2  database rather
    than using raw SQL as in the past. The router forces the use of the DB2
    database for any app in the "apps" list.
    """
    db = "DB2"
    apps = ["analytics"]

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.apps:
            return self.db
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.apps:
            return self.db
        return None

    def allow_relation(self, obj1, obj2, **hints):
        # Allow any relation between two models that are both in the same app.
        if (obj1._meta.app_label in self.apps) and (obj2._meta.app_label  in self.apps):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.apps:
            return db == self.db
        return None

我的模型:

class PartnerImpression(models.Model):
    """ used to track impressions on widgets through our partners """
    partner = models.CharField(max_length=1024)
    referer = models.CharField(default="N/A", max_length=2048)
    created = models.DateTimeField(auto_now_add=True, blank=True)

迁移:

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='PartnerImpression',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('partner', models.CharField(max_length=1024)),
                ('referer', models.CharField(default='N/A', max_length=2048)),
                ('created', models.DateTimeField(auto_now_add=True)),
            ],
        ),
    ]

  • DB2存在并且有一个空的django_migrations表。

  • manage.py migrate --database=DB2命令中定义数据库不是一种选择,因为我在数十台服务器上运行了CI进程,并且无法在所有服务器上手动运行此进程,因此该命令需要保留无参数

  • 我在迁移中不需要任何原始SQL

我也发现了这一点:Django migrations with multiple databases,但我不知道自2016年以来是否发生了任何变化,并且希望找到一种无需使用database选项就可以运行的方法

1 个答案:

答案 0 :(得分:1)

默认情况下,migrate--database的值设为defaultDEFAULT_DB_ALIAS)(如果未提供);因此,将对该数据库应用所有迁移。如果要使用Django提供的即用型功能,则必须使用--database提及要操作的数据库。如果由于某种原因您不能使用它(如您提到的那样),则可以创建一个自定义管理命令,例如migrate_all一次将所有迁移应用于所有数据库。

下面的示例方法仅显示了handle方法的外观,您可以从migrate中汲取灵感:

migrate_all.py

from importlib import import_module
from django.apps import apps
from django.db import connections

class Command(BaseCommand):
    help = "Updates all database schemas."

    def add_arguments(self, parser):
        # Add arguments if you want
        pass

    def handle(self, *args, **options):
        # Import the 'management' module within each installed app, to register
        # dispatcher events.
        for app_config in apps.get_app_configs():
            if module_has_submodule(app_config.module, "management"):
                import_module('.management', app_config.name)

        # Iterate over and operate on each of the databases
        for connection in connections.databases:
            # https://github.com/django/django/blob/master/django/core/management/commands/migrate.py#L84
            connection.prepare_database()
            ...
            ...

connections.databasesfollow the operations from migrations for each获得每个连接后。