Django更新Project状态为done时自动同步关联Task状态的实现问题
Django修改项目状态同步更新关联任务状态解决方案
你之前编写的自定义模型方法没有被自动触发的调用入口,因此逻辑不会执行。针对你的需求有两种常见实现方式:
方案1:重写UpdateView的form_valid方法(仅针对当前编辑视图生效)
适合仅需要在用户通过前端项目编辑页面修改状态时触发同步的场景,代码修改量最小,修改后的视图代码如下:
from django.utils import timezone class ProjectEditView(LoginRequiredMixin, generic.UpdateView): login_url = '/login/' model = Project form_class = ProjectForm template_name = 'project_form.html' success_url = reverse_lazy('project_list') def form_valid(self, form): # 先获取修改前数据库中存储的项目状态 old_status = Project.objects.get(pk=self.object.pk).status # 保存修改后的项目信息 response = super().form_valid(form) # 校验是否是从非完成状态切换为完成状态 if old_status != 1 and self.object.status == 1: # 批量更新关联的所有任务状态 self.object.Tasks.all().update(status=1, updated_on=timezone.now()) return response
方案2:重写Project模型的save方法(全局生效)
适合所有场景下修改项目状态为完成时都同步更新任务的需求,包括Admin后台修改、脚本批量修改等,修改后的Project模型代码如下:
from django.utils import timezone class Project(models.Model): owner = models.ForeignKey('auth.User', on_delete=models.CASCADE) title = models.CharField(max_length=24, unique=True) status = models.IntegerField(choices=STATUS, default = 0) def __str__(self) -> str: return self.title def save(self, *args, **kwargs): # 已存在的项目才需要校验状态变更 old_status = None if self.pk: old_status = Project.objects.get(pk=self.pk).status # 执行原生保存逻辑 super().save(*args, **kwargs) # 状态切换为完成时同步更新关联任务 if old_status != 1 and self.status == 1: self.Tasks.all().update(status=1, updated_on=timezone.now())
补充说明
- 批量更新使用
QuerySet.update()是数据库层面的批量操作,执行效率远高于遍历每个Task实例调用save() - Task模型中关联Project的
related_name定义为Tasks,调用时大小写需要和定义保持一致,否则会抛出属性不存在的错误 - 如果不需要同步更新Task的
updated_on字段,可删除update参数中的updated_on=timezone.now()
内容的提问来源于stack exchange,提问作者Pawelek
相关产品推荐
相关产品推荐

