0

In my problem, the m2m relationship is not getting updated in post_save signal.

I have a post_save that checks to make sure that the user is a staff member and if they don't have default permissions, then they are assigned default permissions. If the user is not staff, then it confirms that they don't have default permissions.

def user_post_save(sender, instance, **kwargs):
    """
        If the user is staff and they don't have default auth permissions
        assign them.
    """
    group_ids = [g.id for g in instance.groups.all()]
    if instance.is_staff and 1 not in group_ids:
        # give them default auth permissions.
        instance.groups.add(1)
    elif not instance.is_staff and 1 in group_ids:
        # if they are not staff and they have the permission, remove it.
        instance.groups.remove(1)

post_save.connect(user_post_save, sender=User)

The problem is that instance.groups makes it to the end of user_post_save with the correct intended values, however it doesn't update in the db. What I am missing?

Thank you ahead of time for your help!


More info: I was playing around and took away staff status from a user with default permissions. When I looked at the postgres logs, I noticed the following:

LOG:  statement: DELETE FROM "auth_user_groups" WHERE "auth_user_groups"."user_id" = 8

A couple of statements later...

LOG:  statement: INSERT INTO "auth_user_groups" ("user_id", "group_id") VALUES (8, 1)

So, it is properly being deleted, there is just something causing it to insert again?


Update:

Here is the repo/branch: https://github.com/jaycrossler/geoq-django/tree/guardian_setup/geoq
Here is the specific location of the signal: https://github.com/jaycrossler/geoq-django/blob/guardian_setup/geoq/accounts/models.py

jackiekazil
  • 5,696
  • 4
  • 21
  • 20
  • Does it work if you edit and save an existing user, but fail when creating a new one? – Peter DeGlopper Nov 27 '13 at 17:29
  • Updated -- was supposed to be post_save, not pre_save, because relationship doesn't exist with new users. @PeterDeGlopper -- to answer your question, it doesn't work for existing users. It is never an option with new users, because new users are default not staff members and do not have permissions. – jackiekazil Nov 27 '13 at 17:35
  • Can you perhaps share your models (and any other overriding you are doing to the signals?) – yuvi Nov 30 '13 at 21:23
  • @yuvi -- I added them to the question. – jackiekazil Nov 30 '13 at 21:54
  • Looking at your project, it seems you're better at django than I am. However, two thoughts I do have: 1) why override signals and not just the save method for the model itself? 2) saving m2m is always a bit of a challange (because you can't link m2m to an object that doesn't exist yet). Perhaps you need to run the [m2m_changed](https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed) signal (or override it as well?) after the post_save – yuvi Nov 30 '13 at 22:18
  • @yuvi -- Thank you for your input. I wouldn't say that I am better, because there are a bunch of people contributing. :-). RE: m2m -- I will look into that. I used the signal instead of the save override, b/c it was the User model. Userena and Guardian pull from django.contrib.auth. Seemed nicer to use signals instead of trying to get subclassed User model to play nicely... if you can tell me a nice way of doing that, I would be more than happy to try it. – jackiekazil Nov 30 '13 at 22:51
  • Lastly, this question http://stackoverflow.com/questions/20305517/does-a-reverse-sql-inspector-exist-for-django-postgres also came about from this problem. I was trying to reverse the problem. – jackiekazil Nov 30 '13 at 22:51
  • `"Seemed nicer to use signals instead of trying to get subclassed User model to play nicely"` - I thought that might be it, though from my experience, when you start messing around with the User, sticking to the defualt is always a headache. I'll try to recreate this thing tomorrow and play around with it a bit. I can't help you with your other question (0 experience with that whatsoever), sorry – yuvi Nov 30 '13 at 23:05
  • No worries. I appreciate the help! Let me know if you have any issues recreating it (or feel free to ticket any issues). :-) – jackiekazil Dec 01 '13 at 02:01
  • Looking at your repo you've implemented this in the UserProfile save method. Did you fix the problem? – hharnisc Dec 06 '13 at 15:58

1 Answers1

1

Is it happen only then using django.admin app? Can you change user status and save it in your own's app? Because django built-in admin does the following:

in the file django.contrib.admin.options.py function change_view approx at 1053 line

if all_valid(formsets) and form_validated:
    self.save_model(request, new_object, form, True)
    self.save_related(request, form, formsets, True)
    change_message = self.construct_change_message(request, form, formsets)
    self.log_change(request, new_object, change_message)
    return self.response_change(request, new_object)

the line self.save_related(request, form, formsets, True) is executed AFTER saving the object at self.save_model(request, new_object, form, True), successfully erasing that you saved in your's user_post_save.

Psion
  • 115
  • 4