【问题标题】:Django: save multiple object signal onceDjango:一次保存多个对象信号
【发布时间】:2010-12-28 14:51:06
【问题描述】:

在下订单时,我需要一些帮助来发送电子邮件。为了说明问题,下面是抽象代码:

class Order(models.Model):
    user = models.ForeignKey(User)

class OrderItem(modes.Model):
    order = models.ForeignKey(Order, related_name='items')
    item = models.CharField(max_length=255)
    unit_price = models.DecimalField()
    qty = models.IntegerField()
    item_amount = models.DecimalField()

def email_order_on_save(sender, instance, **kwargs):
    # Need order.items.all() here
    pass

post_save.connect(email_order_on_save, sender=Order)

SO 和 google 上的大多数问题似乎一次只处理一个子对象; such as this.

如果从管理员内联中保存了 5 个订单项,则收听 OrderItem 将释放 5 个信号。我似乎无法解决这个问题。一种方法,我认为(不确定是否可能),可能是监听最后一个(5)OrderItem 的 post_save 信号。

任何帮助表示赞赏。

【问题讨论】:

    标签: django signals


    【解决方案1】:

    我猜你试图在错误的地方解决这个问题。订单完成时发送电子邮件和保存订单模型处于不同的抽象级别。

    我认为发送电子邮件应该由视图中的某些条件触发,该条件包含有关订单是否完全保存的更多信息。例如,如果订单需要更新(比如状态更改)会发生什么?那么邮件也应该发送吗?

    【讨论】:

    • 我很好奇。您能否详细说明为什么它们是“不同的抽象级别”?如果发送电子邮件是业务逻辑的一部分,它不应该由模型以某种方式触发吗?此外,发送电子邮件的逻辑不需要在每次保存时盲目地发送电子邮件......email_order_on_save 可以接收参数信息,说明这是插入、更新(以及什么样的更新)并发送适当的消息...
    • 好的,模型可能是正确的位置,但保存方法/信号可能不是。 Django 模型有两个用途,一个是作为“模型”层(即业务模型),另一个是将数据持久化到数据库中,它们重叠但不相同。可能需要一个“提交订单”方法,该方法调用 save() 来保存模型,然后在满足适当条件时发送电子邮件(可能使用@celopes 建议的自定义信号。)
    • 感谢 Tom 和 celopes 的意见。我同意celopes。电子邮件“是业务逻辑的一部分”,将在每个订单(连同 OrderItems)创建时发送,可以通过 if kwargs['created']:email_order_on_save 函数中捕获。
    • 啊,我喜欢submit_order 的想法。它将存在于模型中,并具有与保存构成逻辑顺序的模型并提交它(包括电子邮件)相关的所有业务逻辑。为此+1。将此与自定义信号结合起来,您应该会很出色。
    【解决方案2】:

    创建您自己的custom signal 并在您需要保存数据时发送。作为参数传入您需要的任何数据结构。

    Listen for your custom signal 在您的回调函数email_order_on_save 中,并根据有关发送或不发送电子邮件的参数做出适当的决定。

    【讨论】:

    • 作为 Django 新手用户,我不确定那个“点”在哪里,我保存了带有 OrderItems 的订单。我能想到的其他方法是通过异步检查新订单和发送电子邮件来使用django-cron。但这似乎不是最佳解决方案。
    • 我认为汤姆给了你一个很好的建议。与其在视图中调用单独的 model.save 方法,不如在 Order 上创建一个 submit_order 方法并从视图中调用它。请参阅我对汤姆回答的评论。
    • Duh...忘了说:并通过新的submit_order 方法发送您的信号。
    【解决方案3】:

    我认为您可能对信号有问题,带有内联的 OrderItem 不会发送保存信号,请阅读this

    【讨论】:

      【解决方案4】:

      您可以按如下方式创建模型

      ORDER_STATE = (
          (1, 'Completed'),
          (2, 'Processing'),
      )
      
      class Order(models.Model):
          user = models.ForeignKey(User)
          state = models.IntegerField(choices = ORDER_STATE)
      

      订单可以有多个状态。状态“已完成”可以表示订单处理已完成。您可以在视图中更改订单状态。

      在信号处理程序中,您可以检查订单的状态,如果订单处于完成状态,则发送邮件。

      【讨论】:

      • 感谢您的输入 Mayuresh,但您的方法需要手动干预,我宁愿避免。
      猜你喜欢
      • 2021-01-10
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 2017-11-21
      • 2016-12-09
      • 1970-01-01
      相关资源
      最近更新 更多