Django执行migrate时post_migrate信号被多次调用该如何解决?
问题原因
- post_migrate信号的触发机制是每个应用的迁移执行完成后就会发送一次,你执行migrate时共有6个应用需要执行迁移逻辑,所以信号被触发6次,你的接收器函数也对应执行6次
- 额外排查点:如果你的
ready方法被重复调用,会导致信号被多次注册,也会触发重复执行的问题,常见于Django开发模式开启自动重载的场景,会启动两个进程分别加载一次应用配置
解决方案
1. 给信号接收器添加唯一标识,避免重复注册
给@receiver装饰器增加dispatch_uid参数,保证全局只注册一次信号:
# signals.py 修改后 @receiver(post_migrate, dispatch_uid="full_sync_if_model_change_unique_identifier") def full_sync_if_model_change(plan, **kwargs): # 原有逻辑保持不变
2. 增加执行开关,保证同步逻辑全局只执行一次
在signals.py中增加模块级的执行标记,避免多次触发时重复运行同步逻辑:
# signals.py 新增全局标记 SYNC_HAS_RUN = False @receiver(post_migrate, dispatch_uid="full_sync_if_model_change_unique_identifier") def full_sync_if_model_change(plan, **kwargs): global SYNC_HAS_RUN if SYNC_HAS_RUN: return 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) SYNC_HAS_RUN = True return
3. 可选:指定只处理目标应用的信号
如果你的同步逻辑只需要处理特定应用的迁移,可以在函数开头加app配置判断,过滤无关应用的信号触发:
@receiver(post_migrate, dispatch_uid="full_sync_if_model_change_unique_identifier") def full_sync_if_model_change(plan, app_config, **kwargs): # 只处理你的lakehouse_sync应用或者test_models应用的迁移信号 if app_config.name not in ["lakehouse_sync", "test_models"]: return # 剩余原有逻辑
内容的提问来源于stack exchange,提问作者Evandro Lippert
相关产品推荐
相关产品推荐

