当我尝试保存实例时,django post_save信号被触发两次,它实际上是触发更新部分

时间:2018-02-24 18:20:42

标签: django django-models django-signals

我有两种型号Invoce和Payin。发票可以多付款支付。使用post_save信号更新发票详细信息时。执行创建逻辑后,我将一个Invoice Id附加到Payin实例并保存。这个保存再次触发信号(因为它应该是)这次更新逻辑,即在if的其他部分创建:在那里执行一次payin被添加两次到发票中的付款金额。当我在信号逻辑中保存实例时,如何避免更新逻辑。

class Invoice(BaseEntity):
    """ Invoices are generated based on events state"""

    STATUS_CHOICES=(
        ('CREATED', 'Created'),
        ('CONFIRMED', 'Confirmed'),
        ('PARTIAL_PAYMENT', 'Partially Paid'),
        ('RECEIVED', 'Received'),
        ('CLOSED', 'Closed')
    )
    customer = models.ForeignKey(
            Customer,
            related_name='invoices',
        )
    event = models.ForeignKey(
            'booking.Event',
            related_name='invoice',
        )
    generated_date = models.DateField(
            verbose_name='date invoice generated'
        )
    due_date = models.DateField(
            verbose_name='date payment is expected'

        )
    status = models.CharField(
        max_length =15,
        choices = STATUS_CHOICES,
        default = 'CREATED',
    )
    amount = models.IntegerField(
            default=500,
            validators=[
                MinValueValidator(
                    10,
                    message = 'Amount should be greater than 10'
                ),

                MaxValueValidator(
                    10000000,
                    message = 'Amount should be less than 10000000'
                ),
            ]
        )
    paid = models.IntegerField(
            default=500,
            validators=[
                MinValueValidator(
                    10,
                    message = 'Amount should be greater than 10'
                ),

                MaxValueValidator(
                    10000000,
                    message = 'Amount should be less than 10000000'
                ),
            ]
        )

    def get_absolute_url(self):
        return reverse('accounting:Invoice_Detail', kwargs={'pk': self.id})

    def get_update_url(self):
        return reverse('accounting:Invoice_Update', kwargs={'pk': self.id})

    def get_delete_url(self):
        return reverse('accounting:Invoice_Delete', kwargs={'pk': self.id})

class Payin(BaseEntity):
    """ Payins from all customers"""
    MODE_CHOICES=(
        ('BANK', 'Bank'),
        ('CHEQUE', 'Cheque'),
        ('DD', 'Demand Draft'),
        ('CASH', 'Cash'),
    )
    customer = models.ForeignKey(
            'customers.Customer',
            related_name='customer_payins',
            blank = True,
            null = True,
        )
    event = models.ForeignKey(
            'booking.Event',
            related_name='event_payins',
            blank = True,
            null =True,
        )
    date = models.DateField(
            verbose_name='payment date'
        )
    time = models.TimeField(
            verbose_name='payment time'

        )
    amount = models.IntegerField(
            default=500,
            validators=[
                MinValueValidator(
                    10,
                    message = 'Amount should be greater than 10'
                ),

                MaxValueValidator(
                    10000000,
                    message = 'Amount should be less than 10000000'
                ),
            ]
        )
    mode = models.CharField(
        max_length =15,
        choices = MODE_CHOICES,
        default = 'CASH',
    )
    invoice = models.ForeignKey(
            Invoice,
            related_name='payins',
            blank = True,
            null = True,
        )

    def get_absolute_url(self):
        return reverse('accounting:Payin_Detail', kwargs={'id': self.id})

    def get_update_url(self):
        return reverse('accounting:Payin_Update', kwargs={'id': self.id})

    def get_delete_url(self):
        return reverse('accounting:Payin_Delete', kwargs={'id': self.id})    


@receiver(post_save, sender = Payin)
    def update_event_invoice_based_on_payin(sender,instance, created, **kwargs):
        payin = instance
        #print(dir(instance))
    if created:
        try:
            event = Event.objects.get(pk = payin.event.id )
            if event.status != 'COMPLETED':
                print('advance before save in post_save in create is: ', event.advance)
                event.advance = event.advance + payin.amount
                event.save()
                print('advance after save in post_save in create is: ' , event.advance)
            else:
                invoice = Invoice.objects.get(event = event.id)
                if invoice.paid + payin.amount <= invoice.amount:
                    print('post_save before save :',invoice.paid )
                    invoice.paid = (invoice.paid + payin.amount)
                    print(invoice.paid)
                    if invoice.paid == invoice.amount:
                        invoice.status = 'PAID'
                        invoice.save()
                        print('post_save after save in paid :',invoice.paid)
                        payin.invoice = invoice
                        print('paid')
                        payin.save()
                    else:
                        invoice.status = 'PARTIAL_PAYMENT'
                        invoice.save()
                        print('post_save after save in partial payment :',invoice.paid)
                        payin.invoice = invoice
                        print('partial payment')
                        payin.save()
        finally:
            #del instance._del
            pass
    else:
        event = Event.objects.get(pk = payin.event.id )
        if event.status != 'COMPLETED':
            print('advance before save in post_save in modify is: ' ,event.advance)
            event.advance = event.advance + payin.amount
            event.save()
            print('advance after save in post_save in modify is: ' , event.advance)
        else:
            invoice = Invoice.objects.get(event = event.id)
            if invoice.paid + payin.amount <= invoice.amount:
                #print(invoice.paid + payin.amount)
                print('post_save before save in update :',invoice.paid)
                invoice.paid = (invoice.paid + payin.amount)
                print(invoice.paid)
                if invoice.paid == invoice.amount:
                    invoice.status = 'PAID'
                    invoice.save()
                    print('post_save after save in paid in update :',invoice.paid)
                    print('paid')
                else:
                    invoice.status = 'PARTIAL_PAYMENT'
                    invoice.save()
                    print('post_save after save in partial payment in update :',invoice.paid)
                    print('partial payment')

0 个答案:

没有答案