我有一个 django 项目,它有 2 个应用程序,每个应用程序在不同的数据库上运行(我们称它们为 default 和 DB2(。 我创建了一个路由器来管理数据,并将路由器添加到我的settings.py
当我运行 migrate 时,我得到Applying analytics.0001_initial... OK
但在默认数据库中唯一更新的是显示应用程序分析已使用 0001 迁移的django_migrations
表,而在 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 迁移,但我不知道自 2016 年以来是否有任何变化,并且还希望有一种在没有database
选项的情况下让它运行的方法
默认情况下migrate
将--database
值作为default
(DEFAULT_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.databases
获取每个连接后,按照每个连接migrations
中的操作进行操作。