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
相关产品推荐
相关产品推荐

