【问题标题】:Django migration with 2 DBs?带有 2 个数据库的 Django 迁移?
【发布时间】:2021-08-30 13:29:00
【问题描述】:

我有数据库db1db2。应该使用相同的迁移脚本创建两个 DB 的模式。

Django 文档提到了DATABASE_ROUTERSRunPython,但到目前为止我还没有设法让它工作。函数被调用,但migrations.CreateModel()从函数调用时没有影响:没有创建表。

迁移脚本:

# 0001_initial.py

def forwards(apps, schema_editor):
    if schema_editor.connection.alias == 'db1':
        print('This line is called!')
        migrations.CreateModel(
            name='MyModel',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                # ...
            ]
        )

class Migration(migrations.Migration):
    initial = True
    
    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.RunPython(forwards, hints={'target_db': 'db1'}),
    ]

路由器:

DatabaseRouter:
    # ...
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if 'target_db' in hints:
            return db == hints['target_db']
        return True

命令:

python manage.py migrate --database=db1

有什么想法吗?提前致谢!

【问题讨论】:

  • 你为什么不把migrations.CreateModel写在operations列表中呢?实际上,您为什么还要编写迁移以手动制作模型?只需在models.py 中编写模型的代码并运行makemigrations,您将自动获得一个迁移文件...
  • @AbdulAzizBarkat 我需要在某处定义在哪个数据库中创建的模型不是由makemigrations 完成的。你会怎么做?
  • 那当然是在 router 中的allow_migrate 方法中完成的。您将检查传递的app_label 和数据库别名db 并返回True 以防它应该迁移到那里,False 如果不是,None 如果其他路由器应该决定。
  • 感谢您的提示。你有我可以使用和接受的有效答案吗?

标签: python django django-models django-rest-framework django-migrations


【解决方案1】:

migrations.CreateModel 在实例化时不会在数据库中创建模型。它应该出现在operations 列表中,然后迁移系统将使用它来创建模型。此外,无论如何您都不应该手动编写此迁移!只需在models.py中编写模型的代码:

class MyModel(models.Model):
    # Your fields, etc.

接下来,因为您的问题询问如何控制将哪个模型迁移到哪个数据库。这些任务应该在Database router 中完成,尤其是在allow_migrate 方法中。您可以检查为dbapp_labelmodel_name 传递的值,返回是否应将模型迁移到那里。例如:

class MyRouter:
    def db_for_read(self, model, **hints):
        ...

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

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

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        # Suppose I want to migrate all models from the app 'some_app' to 'db1' only.
        if app_label in ['some_app']:
            return db == 'db1'
        # Suppose I want to migrate 'MyModel' to 'db2' only.
        if model_name == 'mymodel':  # 'mymodel' is lowercase 'MyModel'
            return db == 'db2'
        return None

【讨论】:

  • 非常感谢。这正是我想要的。
猜你喜欢
  • 2023-03-28
  • 2018-03-11
  • 2020-03-22
  • 2018-03-04
  • 2016-06-07
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
  • 2014-01-13
相关资源
最近更新 更多