J'utilise le signal post_save de Django pour exécuter certaines instructions après avoir sauvegardé le modèle.
class Mode(models.Model):
name = models.CharField(max_length=5)
mode = models.BooleanField()
from Django.db.models.signals import post_save
from Django.dispatch import receiver
@receiver(post_save, sender=Mode)
def post_save(sender, instance, created, **kwargs):
# do some stuff
pass
Maintenant, je veux exécuter une instruction selon que la valeur du champ mode
a changé ou non.
@receiver(post_save, sender=Mode)
def post_save(sender, instance, created, **kwargs):
# if value of `mode` has changed:
# then do this
# else:
# do that
pass
J'ai consulté quelques fils SOF et un blog, mais je n'ai pas trouvé de solution à ce problème. Tous essayaient d'utiliser la méthode pre_save ou la forme qui ne sont pas mon cas d'utilisation. https://docs.djangoproject.com/es/1.9/ref/signals/#post-save dans la documentation Django ne mentionne pas de moyen direct de le faire.
Une réponse dans le lien ci-dessous semble prometteuse mais je ne sais pas comment l'utiliser. Je ne sais pas si la dernière version de Django le prend en charge ou non, car j’ai utilisé ipdb
pour déboguer ceci et constaté que la variable instance
ne comporte aucun attribut has_changed
, comme indiqué dans la réponse ci-dessous.
Django: Lors de l'enregistrement, comment vérifier si un champ a été modifié?
Configurez-le sur le __init__
de votre modèle pour y avoir accès.
def __init__(self, *args, **kwargs):
super(YourModel, self).__init__(*args, **kwargs)
self.__original_mode = self.mode
Maintenant, vous pouvez effectuer quelque chose comme:
if instance.mode != instance.__original_mode:
# do something useful
Habituellement, il est préférable de remplacer la méthode de sauvegarde plutôt que d’utiliser des signaux.
De Deux scoops de Django : "Utilisez les signaux en dernier recours."
Je suis d'accord avec la réponse de @scoopseven sur la mise en cache de la valeur d'origine sur init, mais je remplace la méthode de sauvegarde si c'est possible.
class Mode(models.Model):
name = models.CharField(max_length=5)
mode = models.BooleanField()
__original_mode = None
def __init__(self, *args, **kwargs):
super(Mode, self).__init__(*args, **kwargs)
self.__original_mode = self.mode
def save(self, force_insert=False, force_update=False, *args, **kwargs):
if self.mode != self.__original_mode:
# then do this
else:
# do that
super(Mode, self).save(force_insert, force_update, *args, **kwargs)
self.__original_mode = self.mode
si vous souhaitez comparer l'état avant et après l'action de sauvegarde, vous pouvez utiliser le signal pre_save
qui fournit votre instance telle qu'elle devrait devenir après la mise à jour de la base de données. Vous pouvez également lire l'état actuel de l'instance dans la base de données et effectuer certaines actions en fonction de la différence.
from Django.db.models.signals import post_save, pre_save
from Django.dispatch import receiver
@receiver(pre_save, sender=MyModel)
def on_cahnge(sender, instance: MyModel, **kwargs):
if instance.id is None: # new object will be created
pass # write your code hier
else:
previous = MyModel.objects.get(id=instance.id)
if previous.field_a != instance.field_a: # fielad will be updated
pass # write your code hier