【问题标题】:signals post_save called twice after updating data in class base view django在类基础视图 django 中更新数据后发出两次调用 post_save 的信号
【发布时间】:2021-04-23 08:44:02
【问题描述】:

所以我一直在解决这个问题,每次我更新我的库存时,它都会调用两次以进行更新,我使用 Django 中内置的类基础视图,但在模型中我有一个发布信号,它会删除产品的库存.我已经使用了dispatch_uid,但它不起作用,或者我在互联网上找到的任何解决方案都无法解决我的问题。

这是我用于更新的类基础视图:

class ItemQtyUpdateClassBaseView(UpdateView):
    template_name = 'components/update/item.html'
    form_class = ItemForm

    def get_context_data(self, **kwargs):
        kwargs['context_title'] = 'Update Order Qty'
        return super(ItemQtyUpdateClassBaseView, self).get_context_data(**kwargs)

    def form_valid(self, form):
        try:
            order_item = OrderModel.objects.get(pk = self.kwargs[self.pk_url_kwarg])
            fetch_product = ProductsModel.objects.get(product_name = order_item.product_name)
            print(fetch_product.qty)
            if fetch_product.dough != None:
                if int(fetch_product.dough.qty) <= 0:
                    messages.error(self.request, 'Not enough qty to order.')
                    return self.form_invalid(form)
            if int(fetch_product.qty) <= 0:
                messages.error(self.request, 'Not enough qty to order.')
                return self.form_invalid(form)
            else:
                self.object = form.save()
                messages.success(self.request, 'Successfully update qty.')
        except Exception as e:
            messages.error(self.request, e)
            return self.form_invalid(form)
        return super(ItemQtyUpdateClassBaseView, self).form_valid(form)

    def form_invalid(self, form):
        return super().form_invalid(form)

    def get_queryset(self):
        return OrderModel.objects.filter(pk = self.kwargs[self.pk_url_kwarg])

    def get_success_url(self):
        return reverse_lazy('core:createorder', kwargs = {
            'typeoforder': self.kwargs['typeoforder']
        })

这是我的带有信号post_save的模型:

class OrderModel(models.Model):
    date = models.DateField(auto_now = True)
    invoice_no = models.ForeignKey(InvoiceModel, on_delete = models.CASCADE)
    product_name = models.CharField(max_length = 150, blank = False, null = True)
    price = models.DecimalField(max_digits = 10, decimal_places = 2)
    qty = models.FloatField(default = 1)

    class Meta:
        db_table = 'orders'
        ordering = ['-pk']

@receiver(post_save, sender = OrderModel, dispatch_uid='signals.ordermodel_removeqty')
def removeQty(sender, instance = None, created = False, **kwargs):
    product = ProductsModel.objects.get(product_name = instance.product_name)
    if product.dough != None:
        dough = DoughModel.objects.get(pk = product.dough.pk)
        dough.qty = abs(dough.qty - (product.qty * instance.qty))
        dough.save()
    else:
        product.qty = abs(product.qty - instance.qty)
        product.save()

【问题讨论】:

  • 你能告诉我触发信号时会发生什么吗?
  • 您需要在 apps.py 中导入信号文件,如果您需要进一步帮助,请告诉我

标签: django django-class-based-views django-signals


【解决方案1】:

您在form_valid() 方法中调用了两次save() 方法:

  1. self.object = form.save()
  2. super(ItemQtyUpdateClassBaseView, self).form_valid(form)

您必须从form_valid() 方法中删除以下行:

self.object = form.save()

看看form_valid(form)(Django Docs) 方法做了什么:

保存表单实例,设置视图的当前对象,并 重定向到 get_success_url()

【讨论】:

  • 另外一点,form_valid 中的验证完全扭曲了视图的使用。应该使用cleanclean_&lt;field&gt; 方法在表单本身中完成类似的验证。
  • 是的,我已经发现了我的错误并且也意识到了这一点,但是为了回答的努力,这是一个正确的解决方案,我会标记它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 2017-10-10
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
相关资源
最近更新 更多