![](/img/trans.png)
[英]How to get inline model in post_save instance (Django Signals)?
[英]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_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()
。
代替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.