我在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中输入的cantidad,然后在模型中用post_save捕获的信号量和与Articulo模型的total_pedido相加,这没有问题,但是添加了两倍相同的数量即,输入3,这将变为total_pedido为6。
答案 0 :(得分:0)
假设当前注释掉的代码没有被注释掉时会发生这种双重更新:
save
所以你不必惊讶于你的信号处理程序被调用了两次。
有一些解决方案可以避免这种双commit=False
次调用(例如将form.save()
传递给pedido.save()
)或(如itzmeontv建议的那样)将此更新从post_save信号移至{{1} } - 但这不会修复潜在的逻辑漏洞:这个代码将被执行每次 Pedido.save()
都会被调用(比如更新另一个)不相关的字段),每次将self.cantidad
一遍又一遍地添加到self.articulo.total_pedido
。
这里有两个解决方案:当您知道需要时,明确更新self.articulo
(但这可能不太可靠),或者不是盲目地添加到articulo.total_pedido
要求articulo
从头开始完全重新计算其值,即:
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()
。
答案 1 :(得分:-1)
取代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)