代码之家  ›  专栏  ›  技术社区  ›  Ralf

仅当对象字段满足某些条件时,django updateview才允许

  •  0
  • Ralf  · 技术社区  · 7 年前

    我想要一个 Invoice 只有在某些日期之间才可以更改;这两个日期存储在数据库中并指示当前打开的月份(以防止用户更改旧发票)。

    在我的公司里,哪里是执行这一限制的最好地方 InvoiceUpdateView 是吗?

    一个简单的解决方案:添加表单验证(方法 InvoiceForm.clean_date() )中。很好,但理想情况下,我希望 发票更新视图 如果 发票联 日期超出了设定的范围,它应该重新定向到 InvoiceDetailView 是的。

    下面的代码可以工作,但是它调用 .get_object() 两次:我必须调用它一次以获取对象日期,然后在父级中再次调用此方法 .get() .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 具有 django 1.11

    1 回复  |  直到 7 年前
        1
  •  0
  •   Ralf    7 年前

    最后我把表格显示在 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
    

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