检查挂起的 Django 迁移

     2023-02-24     165

关键词:

【中文标题】检查挂起的 Django 迁移【英文标题】:Check for pending Django migrations 【发布时间】:2015-10-28 14:31:46 【问题描述】:

在 Django 中,是否有一种简单的方法可以检查所有数据库迁移是否已运行?我找到了manage.py migrate --list,它提供了我想要的信息,但格式不是机器可读的。

对于上下文:我有一个脚本在迁移数据库之前不应开始运行。由于各种原因,从运行迁移的进程发送信号会很棘手。所以我想让我的脚本定期检查数据库以查看是否所有迁移都已运行。

【问题讨论】:

您是否正在运行自动化脚本来检查像 fabric 这样的迁移? ***.com/a/8491203/4325513 【参考方案1】:

简单点:

$ until python manage.py migrate --check ; do echo "Migration not completed" ; done

【讨论】:

【参考方案2】:

./manage.py showmigrations #检查哪些已经进行的迁移已应用或未应用 (或:./manage.py showmigrations someApp #仅针对特定应用)

./manage.py makemigrations --dry-run #检查要进行的迁移 (或:./manage.py makemigrations someApp --dry-run #仅针对特定应用)

./manage.py makemigrations #进行迁移 (或:./manage.py makemigrations someApp #仅针对特定应用)

./manage.py showmigrations #检查哪些已经进行的迁移已应用或未应用 (或:./manage.py showmigrations someApp #仅针对特定应用)

./manage.py sqlmigrate someApp 0001 #查看特定应用程序和迁移的 SQL 更改

./manage.py migrate #apply 迁移 (或:./manage.py migrate someApp #仅针对特定应用)

./manage.py showmigrations #检查哪些已经进行的迁移已应用或未应用 (或:./manage.py showmigrations someApp #仅针对特定应用)

./manage.py makemigrations --dry-run #检查要进行的迁移 (或:./manage.py makemigrations someApp --dry-run #仅针对特定应用)

PS:./manage.py migrate someApp zero #unapply 特定应用的所有迁移

这些命令的文档可以是found here on the Django project's website。

【讨论】:

不错的答案!谢谢 致那些可能试图编辑此答案的人......此答案中的重复步骤并非偶然,如果您花时间理解问题或答案,您就会知道。如果您不检查自己(正如此答案中的重复步骤所鼓励的那样),您将永远无法掌握此过程,而且几乎肯定会破坏某些东西。如果这是一个不复杂、完全安全的过程,那么答案就不会那么长(即使没有重复)。如果没有重大的 Django 开发,我预计不会对这个答案做出任何非常有用的更改。 我唯一要添加的是link to this section of the documentation @KoltonNoreen 添加了指向该页面的链接,但未添加该特定部分。应该做我相信的伎俩。【参考方案3】:

针对 Django 3.2 测试:

python manage.py makemigrations --check --dry-run

预期的输出是:

'No changes detected'

如果模型中没有需要创建迁移的待处理更改

python manage.py migrate --plan

预期的输出是:

'Planned operations: No planned migration operations.'

您可以在带有 call_command 的 python 脚本中使用它,并开发一种方法来检查预期的输出。如果有任何待处理的makemigrations migrate 调用,输出将与预期不同,您可以理解缺少某些内容。

我在 CI/CD 管道上运行它,结果非常好。

【讨论】:

【参考方案4】:

3.1 版本说明

新的 migrate --check 选项使命令在检测到未应用的迁移时以非零状态退出。

https://docs.djangoproject.com/en/3.1/ref/django-admin/#cmdoption-migrate-check

我们终于可以了

python manage.py migrate --check

【讨论】:

【参考方案5】:

1.10 版本说明:

当检测到没有迁移的模型更改时,新的makemigrations --check 选项使命令以非零状态退出。

如果您不想创建迁移,请将其与 --dry-run 结合使用:

python manage.py makemigrations --check --dry-run

请注意,这不会检查是否应用了迁移,它只检查是否创建了迁移文件。

【讨论】:

虽然我认为这是对更重要问题“如何知道我是否需要进行迁移 [然后应用这些迁移]?”的答案。 OP 很可能主要或次要之后,它很容易被解释为不是对实际提出的具体问题的完全答案。我想说所有其他答案都需要一半的过程,而你的答案需要另一半。我觉得从技术上讲,OP 可能只想要一半,但实际上,对于所提出的模糊问题,两半都应该参与任何真正有用的答案。 您列出的命令与 OP 有完全相同的问题:输出不容易机器可读。我不明白你是如何解决这个问题的。 --check 命令对 OP 提出的特定问题给出了一个简单的答案,“是否运行了所有迁移”,它非常适合自动化任务,这正是它存在的原因。 我的不是作为您的直接替代品添加的。我实际上比其他人更喜欢你的答案。只是看起来不完整。 --check 看起来不错(对于它所用于的一小部分过程),尽管行为刚刚从 1.8 发生变化,这很烦人。我会再等一会儿再使用它。至于解析输出,这个过程很复杂,令人讨厌,但 grep 简单且通常不可避免。 :p 至于他的确切问题,我再次认为问题更大,没有“简单”的解决方案。如果我制作一个,将用脚本更新答案。或者其他人可以。 我希望这是正确的答案,但不幸的是它不适用于已创建但未应用的迁移。 如果您不想实际创建迁移,请添加 --dry-run 选项。【参考方案6】:

壳牌

到目前为止我发现的唯一简单的解决方案是运行

./manage.py showmigrations | grep '\[ \]'

如果所有迁移都已应用,它将输出一个空字符串。

但是,它与输出格式密切相关。

Python

我检查了migrate 命令的源代码,看来这应该可以解决问题:

from django.db.migrations.executor import MigrationExecutor
from django.db import connections, DEFAULT_DB_ALIAS


def is_database_synchronized(database):
    connection = connections[database]
    connection.prepare_database()
    executor = MigrationExecutor(connection)
    targets = executor.loader.graph.leaf_nodes()
    return not executor.migration_plan(targets)

# Usage example.
if is_database_synchronized(DEFAULT_DB_ALIAS):
    # All migrations have been applied.
    pass
else:
    # Unapplied migrations found.
    pass

【讨论】:

在 Django 1.7 或更高版本中,您可以使用:./manage showmigrations --list./manage showmigrations --plan【参考方案7】:

我通过查找表 django_migrations 进行了检查,该表存储了所有已应用的迁移。

【讨论】:

我建议您只检查此表以获取信息(对表的更改不适用)。我会继续使用诸如 showmigrations 之类的 django 命令,这样您就不会使数据库处于不一致的状态。【参考方案8】:

试试,

python manage.py migrate --list | grep "\[ \]\|^[a-z]" | grep "[ ]" -B 1

返回,

<app_1>
 [ ] 0001_initial
 [ ] 0002_auto_01201244
 [ ] 0003_auto_12334333

<app_2>
 [ ] 0031_auto_12344544
 [ ] 0032_auto_45456767
 [ ] 0033_auto_23346566

<app_3>
 [ ] 0008_auto_3446677

更新

如果您已更新 Django 版本 >= 1.11,请使用以下命令,

python manage.py showmigrations | grep '\[ \]\|^[a-z]' | grep '[  ]' -B 1

【讨论】:

现在有一个内置的:./manage.py showmigrations accounts (no migrations) admin [X] 0001_initial [ ] 0002_logentry_remove_auto_add ....【参考方案9】:

这是我的 Python 解决方案,用于获取有关迁移状态的一些信息:

from io import StringIO  # for Python 2 use from StringIO import StringIO  
from django.core.management import call_command 

def get_migration_state():
    result = []
    out = StringIO()
    call_command('showmigrations', format="plan", stdout=out)
    out.seek(0)
    for line in out.readlines():
        status, name = line.rsplit(' ', 1)
        result.append((status.strip() == '[X]', name.strip()))
    return result

这个函数的结果是这样的:

[(True, 'contenttypes.0001_initial'),
 (True, 'auth.0001_initial'),
 (False, 'admin.0001_initial'),
 (False, 'admin.0002_logentry_remove_auto_add')]

也许它对你们中的一些人有所帮助..

【讨论】:

【参考方案10】:

使用@Ernest 代码,我为待处理的迁移编写了manage_custom.py。您可以获取待处理迁移列表迁移那些待处理迁移(仅),从而节省您的时间。

ma​​nage_custom.py

__author__ = "Parag Tyagi"

# set environment
import os
import sys
import django
sys.path.append('../')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
django.setup()

from django.core.management import execute_from_command_line
from django.db import DEFAULT_DB_ALIAS, connections
from django.db.migrations.executor import MigrationExecutor


class Migration(object):
    """
    A custom manage.py file for managing pending migrations (only)
    """

    def __init__(self, migrate_per_migration_id=False):
        """
        :param migrate_per_migration_id: Setting this to `True` will migrate each pending migration of any
        particular app individually. `False` will migrate the whole app at a time.

        You can add more arguments (viz. showmigrations, migrate) by defining the argument with prefix as 'ARGV_'
        and create its functionality accordingly.
        """
        self.ARG_PREFIX = 'ARGV_'
        self.MIGRATE_PER_MIGRATION_ID = migrate_per_migration_id
        self.ARGV_showmigrations = False
        self.ARGV_migrate = False

    @staticmethod
    def get_pending_migrations(database):
        """
        :param database: Database alias
        :return: List of pending migrations
        """
        connection = connections[database]
        connection.prepare_database()
        executor = MigrationExecutor(connection)
        targets = executor.loader.graph.leaf_nodes()
        return executor.migration_plan(targets)

    def check_arguments(self, args):
        """
        Method for checking arguments passed while running the command
        :param args: Dictionary of arguments passed while running the script file
        :return: Set the argument variable ('ARGV_<argument>') to True if found else terminate the script
        """
        required_args = filter(None, [var.split(self.ARG_PREFIX)[1] if var.startswith(self.ARG_PREFIX)
                                      else None for var in self.__dict__.keys()])
        if any(k in args for k in required_args):
            for arg in required_args:
                if arg in args:
                    setattr(self, ''.format(self.ARG_PREFIX, arg), True)
                    break
        else:
            print ("Please pass argument: "
                   "\ne.g. python manage_custom.py ".format(required_args, required_args[0]))
            sys.exit()

    def do_migration(self):
        """
        Migrates all the pending migrations (if any)
        """
        pending_migrations = self.get_pending_migrations(DEFAULT_DB_ALIAS)
        if pending_migrations:
            done_app = []
            for mig in pending_migrations:
                app, migration_id = str(mig[0]).split('.')
                commands = ['manage.py', 'migrate'] + ([app, migration_id] if self.MIGRATE_PER_MIGRATION_ID else [app])
                if self.ARGV_migrate and (app not in done_app or self.MIGRATE_PER_MIGRATION_ID):
                    execute_from_command_line(commands)
                    done_app.append(app)
                elif self.ARGV_showmigrations:
                    print (str(mig[0]))
        else:
            print ("No pending migrations")


if __name__ == '__main__':
    args = sys.argv
    migration = Migration()
    migration.check_arguments(args)
    migration.do_migration()

用法:

# below command will show all pending migrations
python manage_custom.py showmigrations

# below command will migrate all pending migrations
python manage_custom.py migrate

PS:请根据您的项目结构设置环境。

【讨论】:

当有任何 SOAP 请求的挂起的实体框架数据库迁移时抛出 SOAP 异常

】当有任何SOAP请求的挂起的实体框架数据库迁移时抛出SOAP异常【英文标题】:ThrowSOAPexceptionwhentherearependingEntityFrameworkdatabasemigrationsforanySOAPrequest【发布时间】:2020-08-2112:05:12【问题描述】:当有待处理的实体框架迁移并且有人... 查看详情

django.db.utils.OperationalError: cannot ALTER TABLE 因为它有挂起的触发事件

】django.db.utils.OperationalError:cannotALTERTABLE因为它有挂起的触发事件【英文标题】:django.db.utils.OperationalError:cannotALTERTABLEbecauseithaspendingtriggerevents【发布时间】:2017-08-0602:10:07【问题描述】:我正在尝试将accepted_answerForeignKey更改为B... 查看详情

Django 1.7 迁移挂起

】Django1.7迁移挂起【英文标题】:Django1.7Migrationshanging【发布时间】:2015-10-3107:15:30【问题描述】:我正在尝试申请django迁移。它变得很好(它很小,它只是将CharField添加到两个不同的模型。但是当我运行实际迁移时它会挂起(... 查看详情

ef在migrationhistory中创建initialcreate,然后打开迁移并且initialcreate有一个新的migrationid导致挂起的迁移问题

我有两个解决方案,没有迁移的基本解决方案(正在生产中,因此我无法擦除数据)现在我已经将其分支以设置迁移并进行一些模型更改。首先,我需要在分支解决方案(第二个解决方案)上设置迁移,以便我可以应用模型更改... 查看详情

Django迁移挂起触发事件

】Django迁移挂起触发事件【英文标题】:Djangomigrationspendingtriggerevent【发布时间】:2016-07-0715:24:40【问题描述】:我编辑了我的模型字段:发件人:principal_contact_info_designation=models.IntegerField()收件人:principal_contact_info_designation=mod... 查看详情

efcodefirst命令步骤

...nstall-PackageEntityFramework1、启用迁移Enable-Migrations 2、为挂起的Model变化添加迁移脚本Add-Migration名字  (在已有数据库中使用CodeFirst时标记当前数据库状态:Add-Migration名字-IgnoreChanges)3、将挂起的迁移更新到数据库U 查看详情

vs2013-执行签入挂起的更改,提示没有挂起的更改(实际代码已修改)

问题描述:当我们将vs服务器上的代码映射到本地的时候,在本地都代码进行编辑修改,通过vs进行上传签入的时候,提示没有挂起的更改;解决方案:工作区-管理工作区-编辑-高级-位置,将服务器改为本地,点击确定即可 查看详情

Powershell:获取所有挂起的任务

】Powershell:获取所有挂起的任务【英文标题】:Powershell:Getallsuspendedtasks【发布时间】:2018-03-1418:26:42【问题描述】:我正在尝试从运行windowsserver2012的终端服务器获取所有挂起的任务。我曾尝试使用带有wmi对象的powershell,如下... 查看详情

ThreadPoolExecutor : 拉出挂起的任务

】ThreadPoolExecutor:拉出挂起的任务【英文标题】:ThreadPoolExecutor:Pullouthangedtasks【发布时间】:2020-07-2222:24:16【问题描述】:我已经实现了ThreadPoolExecutor来调用任务。由于核心/队列大小配置错误,任务似乎挂在I/O上。我想把挂线拉... 查看详情

如何使可能挂起的分叉进程超时?

】如何使可能挂起的分叉进程超时?【英文标题】:HowcanItimeoutaforkedprocessthatmighthang?【发布时间】:2009-12-2609:17:43【问题描述】:我正在编写一个Perl脚本,它将编写一些输入并将这些输入发送到外部程序。该程序挂起的可能性... 查看详情

sh停止挂起的ssh会话(代码片段)

查看详情

使用 Cygwin 挂起的 Heroku 工具带登录

】使用Cygwin挂起的Heroku工具带登录【英文标题】:HerokutoolbeltloginwithCygwinhanging【发布时间】:2015-08-1305:23:33【问题描述】:我可以通过Cygwin使用别名访问Heroku,将以下内容添加到我的~/.bashrcaliasheroku=\'heroku.bat\'这可行,但是当我... 查看详情

如何在事务上设置挂起的回滚?

】如何在事务上设置挂起的回滚?【英文标题】:HowtosetapendingRollbackonaTransaction?【发布时间】:2018-09-0708:37:32【问题描述】:我一直在使用MySQLTransactions来封装在我的方法中执行的几个读/写操作。privatevoidReceiveOrderConfirm(objectsende... 查看详情

在 UI 线程上同步取消挂起的任务

】在UI线程上同步取消挂起的任务【英文标题】:CancellingapendingtasksynchronouslyontheUIthread【发布时间】:2014-01-1912:41:37【问题描述】:有时,一旦我使用CancellationTokenSource.Cancel请求取消挂起的任务,我需要确保任务已正确达到取消... 查看详情

如何在 Angular 4+ 中取消/取消订阅所有挂起的 HTTP 请求

】如何在Angular4+中取消/取消订阅所有挂起的HTTP请求【英文标题】:Howtocancel/unsubscribeallpendingHTTPrequestsinAngular4+【发布时间】:2018-02-1413:43:59【问题描述】:如何在Angular4+中取消/中止所有挂起的HTTP请求。有一个unsubscribe方法可以... 查看详情

使用 TeamCity UI 清除挂起的构建

】使用TeamCityUI清除挂起的构建【英文标题】:ClearpendingbuildswithTeamCityUI【发布时间】:2018-01-3000:47:07【问题描述】:在TeamCity(10.0.4)构建链的最后一步中,几个挂起的构建未能启动。在运行按钮的左侧,更改列上方,我看到:待... 查看详情

android如何比较挂起的意图

】android如何比较挂起的意图【英文标题】:Howdoesandroidcomparependingintents【发布时间】:2015-06-1318:47:38【问题描述】:PendingIntent.FLAG_NO_CREATE的文档内容如下:标志表示如果所描述的PendingIntent不存在,则简单地返回null而不是创建它... 查看详情

使用 apollo 客户端钩子停止挂起的请求

】使用apollo客户端钩子停止挂起的请求【英文标题】:stoppendingrequestswithapolloclienthooks【发布时间】:2020-04-0209:13:54【问题描述】:看起来它的possible可以通过client.stop()取消挂起的请求,但是当我们使用apolloclienthooks而我们没有cli... 查看详情