You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 19:48:02