【问题标题】:RunPython migration on second database在第二个数据库上运行 Python 迁移
【发布时间】:2016-04-20 11:59:52
【问题描述】:

在第二个数据库上使用 RunPython 运行数据库迁移失败

python3 manage.py migrate --database=app

问题在于 apps.get_model 方法采用了已经有最新迁移的默认数据库。

不起作用:

def copy_cpr_cents_to_euros(apps, schema_editor):
    User = apps.get_model('accounting', 'User')
    User.objects.filter(...);

作品:

def copy_cpr_cents_to_euros(apps, schema_editor):
    User = apps.get_model('accounting', 'User')
    User.objects.using('app').filter(...);

有没有办法在迁移中使用给定的数据库,所以在这种情况下,“app”不需要明确声明它,因为它应该适用于两个数据库?

比如:

User.objects.using(database_name).filter(...)

【问题讨论】:

    标签: django django-migrations


    【解决方案1】:
    schema_editor.connection.alias
    

    包含开始迁移的当前数据库的字符串。

    所以每个 RunPython-migration 都必须使用这个别名来手动选择正确的 db。

    例子:

    def copy_cpr_cents_to_euros(apps, schema_editor):
        User = apps.get_model('accounting', 'User')
        db = schema_editor.connection.alias
        User.objects.using('app').using(db).filter(...)
    

    【讨论】:

      【解决方案2】:

      可用于 RunPython 函数的装饰器,以指定它应该针对哪个 DB 执行 [在 Django 1.8 上测试]

      def only_default_db_migration(func):
          return only_databases_migration('default')(func)
      
      
      def only_databases_migration(*db_aliases):
          """Restrict running Data Migrations on wanted databases only"""
          def decorate(func):
              def run_python_func(apps, schema_editor):
                  db_alias = schema_editor.connection.alias
                  if db_alias in db_aliases:
                      return func(apps, schema_editor)
                  else:
                      print(f'Skip RunPython {func.__name__!r} for db with alias {db_alias!r}')
              return run_python_func
          return decorate
      
      

      only_default_db_migration的用法

      
      @only_default_db_migration
      def migrate_spam_check_processed_at(apps, schema_editor):
          apps.get_model("queues","Queue").objects.all().update(check=F('created'))
      
      
      class Migration(migrations.Migration):
      
          operations = [
              migrations.RunPython(migrate_spam_check_processed_at),
          ]
      

      【讨论】:

        猜你喜欢
        • 2020-06-20
        • 2014-11-15
        • 2017-02-21
        • 1970-01-01
        • 2016-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多