Django中如何阻止已有参与者的Prediction被设为取消状态
问题描述
需求:当用户尝试将已有参与者的Prediction对象状态修改为cancelled时,显示警告消息并跳转至仪表盘,阻止状态变更。
当前问题:实现的条件语句未生效,即使对象存在参与者,状态仍会被设置为取消。
相关代码
视图代码
class PredictionUpdate(ProductInline, UpdateView): def get_context_data(self, **kwargs): ctx = super(PredictionUpdate, self).get_context_data(**kwargs) ctx['named_formsets'] = self.get_named_formsets() return ctx def get_current_object(self, id): prediction = Predictions.objects.get(id=id) return { "prediction":prediction } def get_named_formsets(self): return { 'variants': PredictionDataFormSet(self.request.POST or None, self.request.FILES or None, instance=self.object, prefix='variants'), } def dispatch(self, request ,*args, **kwargs): obj = self.get_object() if obj.user != self.request.user: messages.warning(self.request, "You are not allowed to edit this bet!") return redirect("core:dashboard") if obj.status == "finished": messages.warning(self.request, "You cannot edit this bet again, send an update request to continue.") return redirect("core:dashboard") # raise Http404("You are not allowed to edit this Post") return super(PredictionUpdate, self).dispatch(request, *args, **kwargs) def form_valid(self, form): instance = form.instance if instance.participants.exists() and instance.status == 'cancelled': messages.warning(self.request, "You cannot cancel a bet that already have participants") return redirect("core:dashboard") else: form.save() return HttpResponseRedirect(self.get_success_url())
模型代码
STATUS = ( ("live", "Live"), ("in_review", "In review"), ("pending", "Pending"), ("cancelled", "Cancelled"), ("finished", "Finished"), ) class Predictions(models.Model): user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) title = models.CharField(max_length=1000) participants = models.ManyToManyField(User, related_name="participants", blank=True) status = models.CharField(choices=STATUS, max_length=100, default="in_review")
问题原因
form_valid方法中的判断逻辑有误:instance.status == 'cancelled'检查的是数据库中保存的旧状态,而非用户提交的新状态。当用户尝试修改状态为cancelled时,此时instance还是从数据库取出的原对象,状态尚未被表单更新,因此该判断永远不会触发。
解决方案
需要获取用户提交的新状态来做判断,有两种可行方式:
方式一:直接从表单清洗后的数据中获取新状态
def form_valid(self, form): # 获取用户提交的新状态 new_status = form.cleaned_data.get('status') instance = form.instance # 判断:存在参与者且新状态为cancelled if instance.participants.exists() and new_status == 'cancelled': messages.warning(self.request, "不能取消已有参与者的赌注") return redirect("core:dashboard") else: form.save() return HttpResponseRedirect(self.get_success_url())
方式二:生成未保存的修改后实例再判断
如果需要对修改后的实例做更多操作,可以先调用save(commit=False)获取未保存的实例,注意要手动保存多对多关联:
def form_valid(self, form): # 获取修改后的实例(未写入数据库) instance = form.save(commit=False) if instance.participants.exists() and instance.status == 'cancelled': messages.warning(self.request, "不能取消已有参与者的赌注") return redirect("core:dashboard") else: instance.save() # 手动保存多对多字段的关联数据 form.save_m2m() return HttpResponseRedirect(self.get_success_url())
内容的提问来源于stack exchange,提问作者Destiny Franks
相关产品推荐
相关产品推荐

