簡體   English   中英

如何將兩個值相加並用post_save信號保存

[英]How to add two values and save them with post_save signals

我在models.py中使用信號,但是當我求和時,此函數執行兩次,而不僅僅是求和

models.py:

class Articulo(models.Model):
cod_experto = models.CharField(max_length=999, primary_key=True, blank=True)
nombre      = models.CharField(max_length=999, blank=True)
descripcion = models.CharField(max_length=999, blank=True, null=True)
on_delete=models.CASCADE)
stock       = models.IntegerField(blank=True, default=0)
total_pedido =models.IntegerField(blank=True, default=0)

class Pedido(models.Model):
especialidad   = models.ForeignKey('Especialidad')
articulo       = models.ForeignKey('Articulo')
blank=True)
cantidad       = models.IntegerField(blank=True)    default='pendiente')

 def __str__(self):
return '{}'.format(self.especialidad, self.articulo, self.cantidad,   self.estado)

def update_total(sender, instance, **kwargs):
   instance.articulo.total_pedido += instance.cantidad
   instance.articulo.save()

# register the signal
signals.post_save.connect(update_total,sender=Pedido, dispatch_uid="update_stock_count")

views.py

def Cant_ingresar(request, id_pedido, id_especialidad):
especialidad = Especialidad.objects.get(id=id_especialidad)
pedido = Pedido.objects.get(id=id_pedido)
if request.method == 'GET':
  form = PedidoEditForm(instance=pedido)
else:
  form = PedidoEditForm(request.POST, instance=pedido)
  if form.is_valid():
       form.save()
       """
       pedido.estado = 'pendiente'
       pedido.fecha_pedido = datetime.date.today()
       pedido.save()
       especialidad.estado='pendiente'
       especialidad.save()
       """
  return HttpResponseRedirect('/solicitar/lista_active/%s/' % id_especialidad)
return render(request, 'form.html', {'form':form, 'pedido':pedido, 'especialidad':especialidad, 'pedido':pedido}) 

如您所見,我首先保存在views.py的def中輸入的候選信,然后在模型中保存用post_save捕獲的信號,並將其與Articulo模型的total_pedido相加,這沒有問題,但是添加了兩倍的相同的數量,即輸入3,然后轉到total_pedido作為6。

假設在未注釋掉當前注釋掉的代碼時發生此雙重更新:

if form.is_valid():
   # this will call `pedido.save()` once
   form.save()
   # ...
   # adds some things to pedido...
   # ...
   # and here you're saving pedido a second time
   pedido.save()

因此,您不必擔心兩次調用信號處理程序。

有一些解決方案可以避免這種雙重save調用(例如,將commit=False傳遞給form.save() )或(如itzmeontv建議的那樣)將此更新從post_save信號移至pedido.save() - 但這不能解決該問題。邏輯缺陷底層 :這個代碼將被執行每一次 Pedido.save()被調用無論什么原因(如更新另一個不相關的場),每次加self.cantidad一遍又一遍又一遍地以self.articulo.total_pedido

在這里,您有兩種解決方案:要么在知道有需要時顯式更新self.articulo (但這可能不是很可靠),要么不是一味地添加到articulo.total_pedidoarticulo從頭開始完全重新計算其值,即:

from django.db.models import Sum

class Articulo(models.Model):
   # ....

   def update_total_pedido(self):
       result = self.pedido_set.aggregate(total=Sum('cantidad'))
       self.total_articulo = result['total']
       self.save(update_fields=['total_articulo'])

然后在Pedido

from django.db import transaction

class Pedido(models.Model):
    # ...
    def save(self, *args, **kw):
        with transaction.atomic():
            super(Pedido, self).save(*args, **kw)
            self.articulo.update_total_pedido()

還要注意,如果沒有什么阻止刪除Pedido ,您可能還想在刪除時調用Articulo.update_total_pedido()

代替post_save覆蓋save

class Pedido(models.Model):
    .....

    def save(self, *args, **kwargs):
        self.articulo.total_pedido += self.cantidad
        self.articulo.save()
        super(Pedido, self).save(*args, **kwargs) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM