Django post_save 没有触发但是 post_delete 在同一个 signals.py 文件中触发

Django post_save not firing but post_delete in same signals.py file does

我希望有人能向我解释为什么 post_save 不工作而 post_delete 看起来是,它们非常相似并且在同一个 signals.py 文件中:

Django 版本 3+ Python 版本 3+

models.py:

import uuid
from django.db import models
from django.db.models import Sum
from django.conf import settings
from products.models import Product
from shows.models import ShowsTickets

class Order(models.Model):
    order_number = models.CharField(max_length=32, null=False, editable=False)
    full_name = models.CharField(max_length=50, null=False, blank=False)
    email = models.EmailField(max_length=254, null=False, blank=False)
    phone_number = models.CharField(max_length=20, null=False, blank=False)
    country = models.CharField(max_length=40, null=False, blank=False)
    postcode = models.CharField(max_length=20, null=True, blank=True)
    town_or_city = models.CharField(max_length=40, null=False, blank=False)
    street_address1 = models.CharField(max_length=80, null=False, blank=False)
    street_address2 = models.CharField(max_length=80, null=True, blank=True)
    county = models.CharField(max_length=40, null=True, blank=True)
    date = models.DateTimeField(auto_now_add=True)
    delivery_cost = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
    products_total = models.DecimalField(max_digits=6, decimal_places=2, null=True, default=0)
    tickets_total = models.DecimalField(max_digits=6, decimal_places=2, null=True, default=0)
    order_total = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)
    grand_total = models.DecimalField(max_digits=6, decimal_places=2, null=False, default=0)

    def _generate_order_number(self):
        """Generate a random, unique order number using UUID"""

        return uuid.uuid4().hex.upper()

    def update_total(self):
        """Update grand total each time a line item is added,
        accounting for delivery costs.
        """

        self.products_total = (self.productlineitems.aggregate(
            Sum('productlineitems_total'))['productlineitems_total__sum']) or 0
        self.tickets_total = (self.ticketlineitems.aggregate(
            Sum('ticketlineitems_total'))['ticketlineitems_total__sum']) or 0
        self.order_total = self.products_total + self.tickets_total
        self.delivery_cost = settings.STANDARD_DELIVERY_CHARGE
        self.grand_total = self.order_total + self.delivery_cost
        self.save()

    def save(self, *args, **kwargs):
        """Override the original save method to set the order number
        if it hasn't been set already.
        """

        if not self.order_number:
            self.order_number = self._generate_order_number()
        super().save(*args, **kwargs)

    def __str__(self):
        return self.order_number


class OrderLineProductItem(models.Model):
    order = models.ForeignKey(Order, null=False, blank=False, on_delete=models.CASCADE, related_name='productlineitems')
    product = models.ForeignKey(Product, null=False, blank=False, on_delete=models.CASCADE)
    quantity = models.IntegerField(null=False, blank=False, default=0)
    productlineitems_total = models.DecimalField(max_digits=6, decimal_places=2, null=False, blank=False, editable=False)

    def save(self, *args, **kwargs):
        """Override the original save method to set the lineproductitem total
        and update the order total.
        """

        self.productlineitems_total = self.product.price * self.quantity
        super().save(*args, **kwargs)

    def __str__(self):
        return f'{self.product} on order {self.order.order_number}'


class OrderLineTicketItem(models.Model):
    order = models.ForeignKey(Order, null=False, blank=False, on_delete=models.CASCADE, related_name='ticketlineitems')
    ticket = models.ForeignKey(ShowsTickets, null=False, blank=False, on_delete=models.CASCADE)
    quantity = models.IntegerField(null=False, blank=False, default=0)
    ticketlineitems_total = models.DecimalField(max_digits=6, decimal_places=2, null=False, blank=False, editable=False)

    def save(self, *args, **kwargs):
        """Override the original save method to set the lineticketitem total
        and update the order total.
        """

        self.ticketlineitems_total = self.ticket.price * self.quantity
        super().save(*args, **kwargs)

    def __str__(self):
        return f'{self.ticket} on order {self.order.order_number}'

signals.py:

from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from .models import OrderLineProductItem, OrderLineTicketItem


# not being called on update/create
@receiver(post_save, sender=OrderLineTicketItem)
@receiver(post_save, sender=OrderLineProductItem)
def update_on_save(sender, instance, created, **kwargs):
    """Update order total on lineproductitem and
    lineticketitem update/create
    """
    
    print('Hello, signals here!')
    instance.order.update_total()


# works fine and, when called, updates everything accordingly
@receiver(post_delete, sender=OrderLineTicketItem)
@receiver(post_delete, sender=OrderLineProductItem)
def update_on_save(sender, instance, **kwargs):
    """Update order total on lineproductitem and
    lineticketitem delete"""

    print('Hello, signals here!')
    instance.order.update_total()

我还添加了 import signals 到应用程序的配置 class' ready() 方法。

想法是让信号通过 update_total() 方法更新订单的 product_total、ticket_total 和 order_total 字段。

在使用任一项目创建实例或更新实例时,不计算总数。然而,当一个实例被删除时,一切都按预期工作并且 post_delete 信号触发(我用 print() 函数测试了它,如上所示。)

为什么 post_save 部分根本不触发(在创建或更新时)?

好的,我已经解决了这个问题。原来是我菜鸟的疏忽。

我的信号函数同名。将 @post_delete 函数更改为 update_on_delete() - 而不是 update_on_save() - 成功了。