Home > Software design >  Django post_migrate signal been called multiple times
Django post_migrate signal been called multiple times

Time:10-27

I have created a post_migrate with the goal to sync all the data inside the table whenever a migration runs. This is the snippet of the post_migrate file:

# signals.py
@receiver(post_migrate)
def full_sync_if_model_change(plan, **kwargs):
    if plan:
        models_set = set()
        for file, _ in plan:
            for model in file.operations:
                try:
                    model = SyncModel.objects.get(
                        app_name=file.app_label, model_name=model.model_name
                    )
                    models_set.add(model)
                except ObjectDoesNotExist:
                    pass
        print(models_set)
        if models_set:
            for model in models_set:
                model.set_full_sync()
                run_update_sync(model, False)
        return

However, when I run a migration, it is called 6 times; as you can see in the output of migration:

evandro@evandro-340XAA-350XAA-550XAA:~/Desktop/.../test_service$ python3 manage.py migrateOperations to perform:
  Apply all migrations: admin, auth, contenttypes, django_cron, lakehouse_sync, sessions, test_models
Running migrations:
  Applying test_models.0019_auto_20211026_2052... OK
set()
set()
set()
set()
set()
set()

I'll add here also the apps file:

class LakeSyncConfig(AppConfig):
    name = "lake_sync"

    def ready(self):
        """Import signals"""
        import lakehouse_sync.core.delete_action

        from . import signals

I have no idea what to do, I tried to add this return statement, but it doesn't work, because the function is called all the time.

CodePudding user response:

The post_migrate signal is sent once for every app migrated, even if there were no changes. Pass the sender parameter when connecting your signal to only run your function once when your app has migrated

def full_sync_if_model_change(plan, **kwargs):
    ...


class LakeSyncConfig(AppConfig):
    name = "lake_sync"

    def ready(self):
        post_migrate.connect(full_sync_if_model_change, sender=self)
  • Related