Django post save signal getting called twice despite uid

前端 未结 4 1496
[愿得一人]
[愿得一人] 2020-12-16 21:59

I have registered my signal with the callback using the @receiver decorator

@receiver(post_save, sender=User, dispatch_uid=\'ARandomUniqueString         


        
相关标签:
4条回答
  • 2020-12-16 22:31

    I just encountered the same problem. I have a receiver that does something important which must be done only once for each new creation of a model instance in Django. So, I used the post_save signal, but that was being called twice for the creation of each new model instance which I was doing like Profile.objects.create(...). The solution to this problem is the created flag which comes with kwargs. Here's how you can use that flag to make sure your intended action is taken only once:

    @receiver(post_save, sender=Profile)
    def publish_auction(sender, **kwargs):
        if kwargs['created']:
            kwargs['instance'].send_email_confirmation()
    

    I tried the dispatch_uid suggestion from Django docs. It didn't work, but the code I pasted above works.

    0 讨论(0)
  • 2020-12-16 22:33

    Ok so I moved the import to views.py (or models.py and while it was getting imported only once, it was getting called twice.

    The problem was that the post_save signal was getting called when the object was created as well as saved. I have no idea why so I added a workaround which now works

    created = False
    
        #Workaround to signal being emitted twice on create and save
        if 'created' in kwargs:
            if kwargs['created']:
                created=True
    
        #If signal is from object creation, return
        if created:
            return
    

    Edit:

    post_save was getting called twice because I used .create(...) which is equivalent to __init__(...) and .save().

    Conclusion

    dispatch_uid does work and doing single imports is still a good practice.

    0 讨论(0)
  • 2020-12-16 22:37

    I have put the from app.signals import * code in __init__.py

    You should not put anything in your __init__.py file.

    If you remove this from __init__.py, and add it to the bottom of your models.py, it should solve your problem.

    You should also avoid "blind" imports from foo import *

    0 讨论(0)
  • 2020-12-16 22:46

    I had the same problem with post_save and also post_delete signals. It seems that the session object and LogEntry object were being saved as well creating multiple signals despite setting the dispatch_uid.

    What worked for me was:

    from django.contrib.admin.models import LogEntry
    from django.contrib.sessions.models import Session
    
    ....
    
    if sender in [LogEntry, Session]:
        return 
    else:
        # do your thing here
    
    0 讨论(0)
提交回复
热议问题