1

Je dois effectuer certaines actions lorsqu'un champ a changé.Détecter le changement de champ en utilisant post_save au lieu du signal pre_save

Depuis cette action doit travailler avec un objet déjà enregistré, je ne peux pas utiliser le signal pre_save comme ceci:

@receiver(pre_save, sender=reservation_models.Reservation) 
def generate_possible_pairs(sender, instance, **kwargs): 
    try: 
     reservation_old = sender.objects.get(pk=instance.pk) 
    except sender.DoesNotExist: 
     pass # Object is new, so field hasn't technically changed, but you may want to do something else here. 
    else: 
     if not reservation_old.datetime == instance.datetime: # Field has changed 
      do_something(instance) # It would be better to be sure instance has been saved 

Est-il possible d'utiliser post_save signal pour cela?

Je souhaite éviter d'ajouter des attributs temporaires à ce modèle.

+0

première (et la plus importation) question: pourquoi voulez-vous utiliser des signaux ici? (indice: vous pouvez personnaliser la méthode 'save()' de votre modèle à la place). Deuxième question: qu'est-ce qui vous fait penser que vous ne pouvez pas utiliser 'pre_save' pour les objets" déjà sauvegardés "? 'pre_save' n'est pas' pre_create', il est appelé chaque fois que votre instance de modèle est sauvegardée. –

+0

1. Bien que les signaux puissent provoquer un débogage douloureux, il semble que ce soit une solution plus élégante. Si je faisais la détection dans la méthode de sauvegarde prioritaire, je devrais ajouter plusieurs (6) champs supplémentaires. Je dois vérifier deux attributs de date et deux (le datetime est la propriété), le statut et si l'objet a été créé. 2. J'ai pensé que si quelque chose se produisait dans la méthode pre_save (exception, etc.), il n'est pas sauvegardé dans db et commit. –

+0

En ce qui me concerne, la solution la plus «élégante» est la plus simple. Aussi je ne comprends pas pourquoi faire votre travail dans le 'save()' du modèle exigerait n'importe quel champ supplémentaire - vous faites juste la même chose que dans votre gestionnaire de pre_save: chargez la version originale de db (avant de sauver n'importe quoi) et comparez les deux versions (ce qui peut être fait après l'enregistrement). Par rapport au point 2, j'ai peut-être mal interprété votre exigence de "travailler avec des objets déjà sauvegardés" :) –

Répondre

5

En utilisant le signal post_save, vous ne pourrez pas récupérer l'état précédent de db - Mais pourquoi utiliser un signal?

class Reservation(models.Model): 
    def save(self, *args, **kw): 
     old = type(self).objects.get(pk=self.pk) if self.pk else None 
     super(Reservation, self).save(*args, **kw) 
     if old and old.datetime != self.datetime: # Field has changed 
      do_something(self) 

Vous pouvez également lire ceci: https://lincolnloop.com/blog/django-anti-patterns-signals/

-1

Oui, vous pouvez aussi utiliser un post_save. Vous devez cependant vous rappeler que les signaux sont synchrones.

+0

Comment utiliser post_save? Je ne sais pas comment reconnaître le changement dans post_save car l'instance a déjà été enregistrée. –

+0

pre_save tire avant que l'objet ne soit sauvegardé et post_save après l'enregistrement de l'objet, donc il suffit de changer le pre_save à poster enregistrer dans le décorateur @receiver – phacic