Question exécuter le code après la validation de la transaction dans Django


Est-il possible d'exécuter du code après la validation de la transaction dans Django?

Je dois envoyer des messages à un serveur rabbitmq pour un traitement hors ligne, mais le message parvient au consommateur avant que la transaction Django ne soit validée.

Mon message est envoyé dans le signal post_save du modèle. Ce que je recherche, c'est un mécanisme similaire, utilisant des signaux ou autre chose, qui exécuterait du code après la validation (et ne ferait rien si la transaction échoue).

Je n'ai trouvé aucun moyen générique de le faire dans Django. As tu des idées?


16
2018-06-04 12:25


origine


Réponses:


MISE À JOUR 2: django-transaction-hooks était fusionné dans le noyau de Django et publié dans la version 1.9 de Django.

METTRE À JOUR: django-transaction-hooks résout ce problème.

Je ne crois pas qu'il y ait une façon propre de le faire; au moins je ne peux pas penser à un. Vous pouvez utiliser monkeypatch django.db.transaction.commit pour envoyer un signal personnalisé. pas joli mais je pense que ça marcherait.

Pourrait également être intéressant de soulever ce cas d'utilisation sur le Liste de diffusion de django-developers. Les développeurs sont généralement peu enclins à ajouter de nouveaux signaux, mais vous pourriez avoir un bon argument ici (et une réfutation d'un développeur de base pourrait inclure une suggestion utile sur la façon de résoudre votre situation). Vous êtes plus susceptible d'obtenir des réponses si vous attendez la sortie de la version 1.1.


11
2018-06-04 15:13



J'ai implémenté des signaux de transaction (post_commit et post_rollback) par singe patching django: http://gist.github.com/247844


5
2017-12-03 03:15



J'espère que cela peut aider quelqu'un qui utilise Django 1.9 ou une version ultérieure. Depuis 1.9 on_commit est disponible.

Donc, fondamentalement, vous le feriez comme ceci:

from django.db import transaction

transaction.on_commit(
    lambda: send_msg_to_rabbitmqp(param1, param2, ...)
)

Si vous souhaitez garder post_save, vous pouvez toujours utiliser on_commit:

@receiver(pre_save, sender=MyModel)
def my_handler(sender, instance, created, **kwargs):
    transaction.on_commit(
        lambda: send_msg_to_rabbitmqp(instance.id)
    )

5
2018-01-12 12:06



Une possibilité serait de sous-classer le middleware de transaction afin qu'il envoie un signal personnalisé lors de la validation. Votre code pourrait écouter ce signal plutôt que post_save.


1
2018-06-04 13:19



Jettes un coup d'oeil à django-celery-transactions pour une solution à cela.

J'ai récemment terminé la scission et la refactorisation du code de code des signaux sous-jacents en une application autonome signaux django-db.


1
2017-12-24 06:32