web-dev-qa-db-ja.com

保留中のDjango=移行を確認

Djangoでは、すべてのデータベース移行が実行されたかどうかを確認する簡単な方法はありますか? manage.py migrate --list、これは私に必要な情報を提供しますが、その形式はあまり機械可読ではありません。

コンテキスト:データベースが移行されるまで実行を開始しないスクリプトがあります。さまざまな理由から、移行を実行しているプロセスからシグナルを送信するのは難しいでしょう。そのため、スクリプトで定期的にデータベースをチェックし、すべての移行が実行されたかどうかを確認したいと思います。

27
Moss Collum

シェル

私がこれまでに見つけた唯一の簡単な解決策は、実行中です

./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
43
Ernest Ten

1.10リリースノート:

新しい makemigrations --checkオプションは、移行なしのモデル変更が検出された場合に、コマンドをゼロ以外のステータスで終了させます。

15
minusf

試して、

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 version> = 1.11、以下のコマンドを使用、

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

./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#移行の適用
(または:./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#特定のアプリのすべての移行を適用解除

7
Jan Kyu Peblik

@Ernestコードを使用して、 manage_custom.py 保留中の移行の場合。 保留中の移行のリストも取得できます移行これらの保留中の移行(のみ)により、時間を節約できます。

manage_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 [〜#〜]:プロジェクト構造に従って環境を設定してください。

テーブルを検索して確認しましたDjango_migrations、適用されたすべての移行を保存します。

移行状態に関する情報を取得するための私のPython soloutionです:

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')]

たぶんそれはあなた方の何人かを助ける..

0
chsymann