【问题标题】:Programmatically check whether there are django south migrations that need to be deployed以编程方式检查是否有 django 南迁移需要部署
【发布时间】:2011-10-28 17:34:10
【问题描述】:

我的部署策略如下所示(使用 Fabric):

  1. 创建一个新的虚拟环境
  2. 在新的 virtualenv 中部署新代码
  3. 显示维护页面
  4. 将当前数据库复制到新数据库
  5. 迁移新数据库
  6. 将新代码指向新数据库
  7. 将当前 virtualenv 符号链接到新 venv
  8. 重启服务
  9. 删除维护页面

我想快速迭代。现在,大多数代码更改不包含迁移。此外,数据库正在增长,因此每次我部署(大部分是很小的)更改时复制数据库都会产生很多开销。为了避免复制数据库,我想检查是否有需要部署的迁移(在步骤 4 之前)。如果没有迁移,我可以直接从第 2 步转到第 7 步。如果有,我将按照所有步骤进行操作。为此,我需要以编程方式检查是否需要部署迁移。我该怎么做?

【问题讨论】:

    标签: django data-migration django-south


    【解决方案1】:

    在部署新代码的第 2 步中,您可以部署一个脚本,该脚本在服务器上运行时会检测是否有新的迁移。

    示例代码如下:

    # copied mostly from south.management.commands.migrate
    from south import migration
    from south.models import MigrationHistory
    
    apps  = list(migration.all_migrations())
    
    applied_migrations = MigrationHistory.objects.filter(app_name__in=[app.app_label() for app in apps])
    applied_migrations = ['%s.%s' % (mi.app_name,mi.migration) for mi in applied_migrations]
    
    num_new_migrations = 0
    for app in apps:
        for migration in app:
            if migration.app_label() + "." + migration.name() not in applied_migrations:
                num_new_migrations = num_new_migrations + 1
    
    return num_new_migrations
    

    如果您将上述代码封装在一个脚本中,您的结构部署脚本可以使用运行操作来获取新迁移的数量。

    如果返回零,那么您可以跳过与复制数据库相关的步骤。

    【讨论】:

    • 感谢 Philip 提供代码。这几乎就是我实现它的方式。效果很好,已经使用这种方法进行了很多有迁移和没有迁移的部署。
    【解决方案2】:
     ./manage.py migrate --all --merge --list | grep "( )"
    

    会告诉您哪些迁移。如果您想要返回码或计数,请使用 wc。

    这样做的好处是不会像接受的答案那样复制和粘贴代码(违反 DRY),而且如果内部南 api 发生更改,您的代码仍然可以工作。

    更新:

    Django 1.7 将输出更改为使用括号而不是括号,并且 Django 1.8 引入了 showmigration 命令:

    ./manage.py showmigrations --list | grep '[ ]'
    

    【讨论】:

    • 简单明了,我喜欢这个。
    • 只是为了 100% 清楚 - 这会应用任何未应用的迁移吗?还是会简单地列出未应用的迁移?
    • 它只会列出而不应用任何东西。绝对安全。
    【解决方案3】:

    dalore 的答案已针对 Django 1.7+ 更新

    ./manage.py migrate  --list | grep "\[ ]"
    

    如果你只想要计数,那么:

    ./manage.py migrate  --list | grep "\[ ]" | wc -l
    

    【讨论】:

      【解决方案4】:

      为什么要移动数据库?迁移的全部意义在于将您在开发中所做的更改应用到您的生产数据库中。

      你的步骤真的应该是:

      1. 创建一个新的虚拟环境
      2. 在新的 virtualenv 中部署新代码
      3. 显示维护页面
      4. 迁移新数据库
      5. 将当前 virtualenv 符号链接到新 venv
      6. 重启服务
      7. 删除维护页面

      如果没有实际的新迁移要运行,迁移步骤不会花费那么长时间。它只会运行每个应用程序,说它已经是最新的。

      如果您要复制数据库以进行备份,那无论如何都应该在 cron 或其他东西上运行,而不是作为部署的一部分。

      实际上,我每次都对创建新的 virtualenv 感到困惑。标准化(阅读:最典型的)部署是:

      1. 部署新代码
      2. 迁移数据库
      3. 重启服务

      如果您想在维护页面中添加回内容,可以,但该过程总共只需要一两分钟。

      【讨论】:

      • 我的策略的目的是能够快速回滚。回滚我的策略只是符号链接到仍然指向正确数据库的先前 virtualenv 的问题。根据您的建议,如果出现问题,您将被迁移的数据库和难以回滚的 virtualenv 困住。要回滚数据库,您需要一个不太可能是最新的备份数据库。此外,不建议使用 South 回滚。如果没有迁移,我想坚持我的策略,但不复制和迁移数据库。所以,我的问题仍然存在。
      • 为什么不推荐使用 South 回滚?如果您正确设置了南迁移,这样数据就不会被删除,只会四处移动,那么回滚迁移是完全合乎情理的。这就是迁移的全部目的。
      • 我认为 South (Andrew Godwin) 的作者自己说过 (Djangocon EU 2011)。虽然我可能误解了它。如果正确设置向后迁移没有真正的问题,我可能应该这样做。
      • 另一方面,使用向后迁移的一个可能问题是它们必须绝对正确,否则它们本身可能会成为失败点。您最终可能会得到一个错误地向后迁移的数据库。由于我正在尝试尽可能地自动化,因此不必检查和测试向后迁移是一个巨大的优势。
      • 我可以看到这个论点,但我认为进行良好的向后迁移与其他任何事情一样重要。回滚迁移的原因不仅仅是“某些事情不能正常工作”。这是数据库结构的一种版本控制形式,如果您想在模型处于比现在更好的状态时将源回滚到特定版本,那么拥有良好的向后迁移将是救命稻草。此外,您可能并不总是管理系统的人。如果后来的一些开发人员期望迁移能够正常工作,那么您的系统就会出现故障。
      猜你喜欢
      • 2013-06-22
      • 2013-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-20
      • 1970-01-01
      • 1970-01-01
      • 2014-10-28
      相关资源
      最近更新 更多