2009-12-21 10 views
1

Мне нужна помощь при отправке электронной почты при размещении заказа. Чтобы проиллюстрировать эту проблему, следующее абстрактный код:Django: сохранить несколько сигналов объекта один раз

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.

Прослушивание OrderItem высвобождает 5 сигналов, если 5 заказов сохранены из встроенных в admin. Кажется, я не могу решить эту проблему. Один из способов, я думаю (не уверен, если возможно), мог бы слушать последние (5) сигналы post_save OrderItem.

Любая помощь приветствуется.

ответ

1

Создайте свой собственный custom signal и отправьте его в тот момент, когда у вас есть необходимые данные. Перейдите в качестве параметров любых структур данных, которые вам нужны.

Listen for your custom signal в вашей функции обратного вызова email_order_on_save и принимать соответствующие решения на основе параметров отправки или отсутствия электронной почты.

+0

Будучи новичком пользователя Django, я не уверен, где эта точка была бы там, где у меня есть заказ с OrderItems. Другим способом, который я мог бы подумать, является использование 'django-cron' путем асинхронной проверки новых заказов и отправки электронной почты. Но это не кажется оптимальным решением. – Nav

+0

Я думаю, что Том дал вам отличное предложение. Вместо того, чтобы, по мнению, вызывать отдельные методы model.save, создать метод 'submit_order' для Order и вызвать это из представления. Смотрите мой комментарий на ответ Тома. – cethegeek

+0

Duh ... Забыл сказать: и отправить свой сигнал из нового метода 'submit_order'. – cethegeek

3

Я предполагаю, что вы пытаетесь решить это не в том месте. Отправка электронной почты при завершении заказа и сохранение модели заказа на разных уровнях абстракции.

Я думаю, что отправка сообщения должна быть вызвана некоторым состоянием в представлении, которое содержит больше информации о том, полностью ли сохранен заказ. Подумайте, например, о том, что произойдет, если заказ нуждается в обновлении (скажем, это изменения статуса)? Должна ли быть отправлена ​​электронная почта?

+0

Мне любопытно. Не могли бы вы объяснить, почему они «разные уровни абстракции»? Если отправка электронной почты является частью бизнес-логики, не следует ли ее каким-то образом запускать модели? Кроме того, логика отправки электронной почты не должна просто слепо отправлять электронную почту при каждом сохранении ... 'email_order_on_save' может получать информацию о параметрах, если это вставка, обновление (и какие обновить) и отправить соответствующее сообщение ... – cethegeek

+0

Хорошо, модель может быть в нужном месте, но метод/сигнал сохранения может не быть. Модели Django служат для двух целей: один является «модельным» слоем (т. Е. Бизнес-моделью), другой - данными, хранящимися в базе данных, они перекрываются, но не идентичны. Может понадобиться метод «отправить заказ», который вызывает save(), чтобы сохранить модель, затем отправляет электронное письмо, если соответствующие условия выполняются (возможно, используя специальный сигнал, предложенный @celopes.) – Tom

+0

Спасибо Tom и celopes для ваш вход. Я согласен с celopes. Электронная почта «является частью бизнес-логики» и должна быть отправлена ​​на каждый заказ (вместе с OrderItems), который может быть захвачен 'if kwargs ['created']:' внутри функции 'email_order_on_save'. – Nav

0

Я думаю, что вы можете иметь проблемы с сигналами, OrderItem с инлайн не будет посылать сохранить сигнал, прочитать this

1

Вы можете создать свою модель следующим образом

ORDER_STATE = (
    (1, 'Completed'), 
    (2, 'Processing'), 
) 

class Order(models.Model): 
    user = models.ForeignKey(User) 
    state = models.IntegerField(choices = ORDER_STATE) 

Вы могли бы иметь много состояний для заказ. Состояние «Завершено» может означать, что обработка заказа завершена. Вы можете изменить состояние своего заказа в своих представлениях.

В обработчике сигналов вы можете проверить состояние заказа и затем отправить почту, если заказ находится в завершенном состоянии.

+0

Спасибо за ваш вклад Mayuresh, но ваш метод потребует ручного вмешательства, которое я бы предпочел избежать. – Nav

Смежные вопросы