Запустить код после совершения транзакции в Django
Есть ли способ запустить некоторый код после транзакции в Django?
Мне нужно отправить некоторые сообщения на сервер rabbitmq для автономной обработки, но сообщение доходит до потребителя до совершения транзакции Django.
Мое сообщение отправлено в сообщении post_save модели. То, что я ищу, - это аналогичный механизм, используя сигналы или что-то еще, которые выполняли бы код после фиксации (и ничего не предпринимают, если транзакция терпит неудачу).
Я не нашел никакого общего способа сделать это в Django. У вас есть идеи?
Ответы
Ответ 1
UPDATE 2: django-transaction-hooks был объединен в ядро Django и выпущен в версии Django 1.9.
UPDATE: django-transaction-hooks решает эту проблему.
Я не верю, что есть чистый способ сделать это; по крайней мере, я не могу думать об этом. Вы можете отправить monkeypatch django.db.transaction.commit для отправки пользовательского сигнала; не очень, но я думаю, что это сработает.
Также может быть интересно поднять этот прецедент в списке рассылки django-developers. Разработчики, как правило, не склонны добавлять новые сигналы, но здесь у вас может быть хороший случай (и опровержение от основного разработчика может включать полезное предложение о том, как разрешить вашу ситуацию). Скорее всего, вы получите ответы, если подождать, пока не появится 1.1.
Ответ 2
Я реализовал сигналы транзакций (post_commit
и post_rollback
) с помощью деманга обезьяны:
http://gist.github.com/247844
Ответ 3
Надеюсь, это поможет кому-то, кто использует Django 1.9 или новее. Начиная с версии 1.9 on_commit.
Итак, в основном вы делаете это так:
from django.db import transaction
transaction.on_commit(
lambda: send_msg_to_rabbitmqp(param1, param2, ...)
)
Если вы хотите сохранить post_save
, вы все равно можете использовать on_commit
:
@receiver(pre_save, sender=MyModel)
def my_handler(sender, instance, created, **kwargs):
transaction.on_commit(
lambda: send_msg_to_rabbitmqp(instance.id)
)
Ответ 4
Одна из возможностей заключается в подклассе промежуточного программного обеспечения транзакции, чтобы он посылал собственный сигнал при фиксации. Ваш код мог бы прослушать этот сигнал, а не post_save.
Ответ 5
Посмотрите django-celery-transactions для решения этой проблемы.
Недавно я закончил разделение и рефакторинг кода кодов базовых сигналов в автономное приложение django-db-signals.