如何判断Django链式lifecycle hooks/signals全部执行完成?
解决方案
最优方案:后端自动执行计算,无需前端二次请求
默认情况下django-lifecycle的AFTER_CREATE钩子为同步阻塞执行,你创建顶层Herd时触发的链式创建操作会全部在当前请求的事务内完成,完全可以在链式创建结束后自动触发总年龄计算,前端不需要额外调用接口。
代码修改步骤:
- 先补全Herd模型缺失的parent字段(你现有代码中创建Herd时传了parent参数但模型未定义):
class Herd(models.Model): animal = OneToOneField(Animal, on_delete=models.CASCADE) # 补充parent外键字段 parent = models.ForeignKey("self", null=True, blank=True, related_name="children", on_delete=models.CASCADE) total_age = IntegerField(null=True, blank=True) @hook(AFTER_CREATE) def create_animal_child(self): if self.animal.child.exists(): Herd.objects.create(parent=self, animal=self.animal.child) # 判断当前为顶层Herd(对应的Animal没有父节点),此时所有子Herd已全部创建完成 if self.animal.parent_id is None: self.save_total_age() # 保存计算结果到数据库 self.save(update_fields=["total_age"]) def save_total_age(self): total_age = self.animal.age position = self.animal while position.child.exists(): total_age += position.child.age position = position.child # 补充赋值逻辑,原有代码缺了这行 self.total_age = total_age
- 前端调整逻辑:创建Herd的接口返回时,响应数据中已经包含计算完成的
total_age字段,直接使用即可,不需要再调用save_total_age接口。
备选方案:保留前端调用逻辑,加重试机制
如果业务逻辑要求必须由前端触发计算,可以采用你想到的数量校验方案,配合前端重试实现:
后端修改
给save_total_age接口加校验逻辑:
- 先统计当前Animal链的总节点数
- 再统计对应已经创建的Herd总数量
- 二者不相等时返回
425 Too Early状态码,提示前端重试
前端修改
把原有回调逻辑改为带重试的async/await逻辑:
const initHerd = async (animalId) => { // 创建顶层Herd const { data: herd } = await axios.post("example.com/api/herds/", { animal_id: animalId }) const maxRetry = 5 let retryTimes = 0 while (retryTimes < maxRetry) { try { await axios.post(`example.com/api/herds/${herd.pk}/save_total_age`) // 计算成功,跳出循环 break } catch (err) { if (err.response?.status === 425) { retryTimes++ // 间隔500ms重试 await new Promise(resolve => setTimeout(resolve, 500)) } else { // 非超时错误直接抛出 throw err } } } if (retryTimes >= maxRetry) { alert("计算超时,请稍后重试") } }
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

