只有对象字段满足特定条件时,Django UpdateView才允许使用

时间:2018-07-13 18:35:55

标签: python django

我希望Invoice仅在某些日期之间可以更改;这两个日期存储在数据库中,并指示当前的开放月份(以防止用户更改旧发票)。

在我的InvoiceUpdateView中执行此限制的最佳位置是哪里?

一个简单的解决方案:添加表单验证(方法InvoiceForm.clean_date())。可以,但是理想情况下,如果InvoiceUpdateView日期不在既定范围内,我希望Invoice甚至不显示表单,它应该重定向回InvoiceDetailView

以下代码有效,但是它两次调用.get_object():我必须调用一次它以获取对象日期,然后在父级.get()或{{1}中再次调用此方法。 }。

.post()

有人有更好的建议/方法吗?还是坚持简单的表单验证是一个很好的论据?

重要的是:class Invoice(models.Model): date = models.DateField() ... more fields ... class InvoiceUpdateView(PermissionRequiredMixin, UpdateView): permission_required = ... template_name = ... model = Invoice fields = ... def can_be_modified(self): # fetch from DB start_date = ... end_date = ... if start_date <= self.object.date <= end_date: return True return False def get(self, request, *args, **kwargs): self.object = self.get_object() if not self.can_be_modified(): return redirect('invoice-detail') return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() if not self.can_be_modified(): return redirect('invoice-detail') return super().post(request, *args, **kwargs) python 3.5

1 个答案:

答案 0 :(得分:0)

我最终还是在InvoiceUpdateView中显示了表格;现在,我没有在GET请求中重定向,而是仅在表单中显示警告消息。我禁止在Invoice请求中更新POST实例。

class InvoiceUpdateView(PermissionRequiredMixin, UpdateView):
    permission_required = ...
    template_name = ...
    model = Invoice
    fields = ...

    @cached_property
    def can_be_modified(self):
        # fetch from DB
        start_date = ...
        end_date = ...

        if start_date <= self.object.date <= end_date:
            return True
        return False

    def form_valid(self, form):
        if not self.can_be_modified:
            messages.error(self.request, 'date is not in range')
            return redirect('invoice-detail')

        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)

        if not self.can_be_modified:
            messages.error(self.request, 'date is not in range')

        return ctx

这不是最优雅的解决方案,但对于我的情况来说已经足够了。