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

Django DRF中post_save信号重复创建PackageDetail记录问题

问题原因

重复创建的核心原因是同一个Tier实例触发了两次update_package_details函数:

  • 视图中tier.save()后,你手动调用了一次update_package_details
  • 同时,你注册的post_save信号会在tier.save()完成时自动触发,再次执行该函数
修复方案

方案1:移除视图中的手动调用(推荐)

直接删除视图里手动调用信号处理函数的代码,让Django的post_save信号自动处理即可:

修改TierCreateView的post方法:

# ... 其他代码不变
if tier_serializer.is_valid():
    tier = tier_serializer.save()
    # 删掉下面这行手动调用的代码
    # update_package_details(sender=Tier, instance=tier, created=True)
    created_tiers.append(tier_serializer.data)
# ... 其他代码不变

方案2:优化信号逻辑,防止重复创建(额外保障)

为了从根源避免重复记录,建议在PackageDetail模型中添加唯一约束,确保同一个package_id和tier_id只能关联一次:

修改PackageDetail的Meta类:

class Meta:
    db_table = "package_detail"
    unique_together = ('package_id', 'tier_id')  # 添加这一行

同时,信号里的创建逻辑可以改用get_or_create,避免重复插入:

@receiver(post_save, sender=Tier)
def update_package_details(sender, instance, created, **kwargs):
    if created:
        plan_id = instance.plan_id_id
        # 先找到关联该Plan的Package记录
        package_query = Package.objects.filter(plan_id=plan_id)
        if package_query.exists():
            package = package_query.first()
            # 使用get_or_create,避免重复创建
            new_package_detail, created_flag = PackageDetail.objects.get_or_create(
                package_id=package,
                tier_id=instance,
                defaults={
                    'details': {},
                    'tenant_id': instance.tenant_id
                }
            )

这样即使因为其他原因触发多次,也只会创建一条记录。

内容的提问来源于stack exchange,提问作者Gerry Volta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:47:29