post_migrate信号-在所有迁移之后只调用一次



在这个(非常简化的(示例中,在所有应用程序迁移后,我需要做一件事(调用do_something_after_all_apps_migrated()(。

问题是,每个应用程序都会调用一次post_migrate信号。

我有一个应用程序:after_migrations

应用程序.py

from django.apps import AppConfig
from django.db.models.signals import post_migrate
from django.dispatch import receiver

class AfterMigrationsConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'after_migrations'
    def ready(self):
        @receiver(post_migrate)
        def _post_migrate(sender,**kwargs):
            app_name = kwargs['app_config'].name
            if app_name == 'after_migrations':
                do_something_after_all_apps_migrated() 

正如你所看到的,这是可行的,但问题是不能保证我的应用程序(after_migrations(是最新迁移的应用程序。这意味着数据库结构不能得到保证。

迁移完所有内容后,如何调用do_something_after_all_apps_migrated()?它不一定是一个信号。

我不得不重写migrate命令并使用信号来实现这一点:

# app/signals.py
from django import dispatch

migrate_finished = dispatch.Signal()
# app/management/commands/migrate.py
from django.core.management.base import no_translations
from django.core.management.commands.migrate import Command as MigrateCommand
from ...signals import migrate_finished

class Command(MigrateCommand):
    @no_translations
    def handle(self, *args, **options):
        super().handle(*args, **options)
        migrate_finished.send(self)

有了这个,您可以监听migrate_finished信号来触发迁移后的代码。

您还可以使用以下功能检查是否在发送信号之前或处理信号之前应用了所有迁移:

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

def is_database_synchronized():
    # The code is from django/core/management/commands/migrate.py
    connection = connections[DEFAULT_DB_ALIAS]
    connection.prepare_database()
    executor = MigrationExecutor(connection)
    targets = executor.loader.graph.leaf_nodes()
    return not executor.migration_plan(targets)

最新更新