0

I placed a breakpoint inside my handler invoked by:

def handle_user_save(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
        EmailNotifications.objects.create(user=instance)
    else:
        import pdb;pdb.set_trace()

post_save.connect(handler_user_save, sender=User)

Within pdb:

(Pdb) dir(instance)
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', '_base_manager', '_default_manager', '_deferred', '_get_FIELD_display', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', '_perform_unique_checks', '_set_pk_val', '_state', 'addressbookentry_set', 'blogcomment_set', 'blogentry_set', 'check_password', 'clean', 'clean_fields', 'date_error_message', 'date_joined', 'delete', 'email', 'email_user', 'emailnotifications', 'first_name', 'full_clean', 'get_absolute_url', 'get_all_permissions', 'get_full_name', 'get_group_permissions', 'get_next_by_date_joined', 'get_next_by_last_login', 'get_previous_by_date_joined', 'get_previous_by_last_login', 'get_profile', 'groups', 'has_module_perms', 'has_perm', 'has_perms', 'has_usable_password', 'id', 'is_active', 'is_anonymous', 'is_authenticated', 'is_staff', 'is_superuser', 'last_login', 'last_name', 'logentry_set', 'natural_key', 'objects', 'password', 'pk', 'prepare_database_save', 'project_set', 'save', 'save_base', 'serializable_value', 'set_password', 'set_unusable_password', 'unique_error_message', 'user_permissions', 'username', 'userprofile', 'validate_unique', 'vote_set']

and:

(Pdb) instance.groups.all()
[]

It doesn't appear to show the changes at this point. But that's most probably the case since I am making a db query to fetch the groups. Is there any other place I can intercept updates to the user model?

Or maybe one of those instance fields will give me the answer? None of those clean methods/fields seem contain anything useful.

TheOne
  • 10,819
  • 20
  • 81
  • 119

1 Answers1

3

Since the relation between User and Group is a ManyToManyField, modifications in this relation triggers another signal: m2m_changed. From the documentation:

Sent when a ManyToManyField is changed on a model instance. Strictly speaking, this is not a model signal since it is sent by the ManyToManyField, but since it complements the pre_save/post_save and pre_delete/post_delete when it comes to tracking changes to models, it is included here.

Therefore, you can check if the groups of a particular user have changed with this:

def handle_m2m_changed(sender, instance, action, **kwargs):
    if action == 'post_add' or action == 'post_remove':
        print(instance.groups.all())

m2m_changed.connect(handle_m2m_changed, sender=User.groups.through)
borges
  • 3,627
  • 5
  • 29
  • 44
  • Thanks I decided to go with different logic, not requiring that code. – TheOne May 27 '12 at 19:01
  • This works but the only problem (for me) is that I want to take an action ONCE after all changes are complete. When multiple groups are added or deleted in a single transaction, you get multiple signals. If the action one needs to take is expensive, repeating it so many times is a problem. The only solution I can think of is to set a flag somewhere and then handle it in middleware as the response is being sent. – little_birdie Dec 07 '18 at 02:09