Update the instance after save, using signals by conditionally refference back to the instance in some cases

烈酒焚心 提交于 2019-12-25 16:39:09

问题


I have the following abstract class:

class UserStamp(models.Model):
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True,
                                   related_name='%(app_label)s_%(class)s_created_by', on_delete=models.CASCADE)
    updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
                                   related_name='%(app_label)s_%(class)s_updated_by', on_delete=models.CASCADE)

    class Meta:
        abstract = True

I have a custom User that inherits from User.

class User(AbstractBaseUser,PermissionsMixin, UserStamp):
    account = models.ForeignKey(Account, blank=True, null=True, related_name='owner',on_delete=models.CASCADE)

The User can create/update himself or by other user.

When the user create/update himself I don't have anything for created_by, update_by.

The user can be created using Django Admin or outside Django Admin;

In Django Admin the user can be created by staff, outside Django is self created;

Also there is superuser that is created in terminal;

Regarding the update the user in both Django Admin and outside can be self updated or by another user.

I thought on using post_save or a custom signal. The issue is that request.user is not available in the model, but in View, and controlling the View in Admin and also in terminal(superuser) is a bottleneck.

Maybe trying to do a query after save passing the instance, but I don't exactly know how to combine all of them signal/query, check superuser.


回答1:


Create your own custom signals.

signals.py

from django.dispatch import Signal 
# you can pass any number of arguments as per your requirement.
manage_user = Signal(providing_args=["user", "is_updated"])


def user_handler(sender, **kwargs):
    # `user` who created/updated object i.e `request.user`
    user = kwargs['user']
    # `is_updated` will be `False` if user object created.
    is_updated = kwargs['is_updated']
    # `sender` is the user object which is created/updated.
    ...
    # do your stuff

manage_user.connect(user_handler)

models.py

Override save() method of your custom user class.

from .signals import manage_user

class User(...):
    ...
    # call this save method like obj.save(created_by=request.user)
    def save(self, created_by, *args, **kwargs):
        super().save(*args, **kwargs)
        # is_updated will be True if user object is updated 
        manage_user.send(sender=self, user=created_by, is_updated=True if self.id else False)

send manage_user signal when user model changed, just like post_save signal, but now you have control over parameters.

UPDATE

If you are using django admin to create user you can overide save_model, you have request object there.

from django.contrib import admin

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
     def save_model(self, request, obj, form, change):
         super(UserAdmin, self).save_model(request, obj, form, change)
         manage_user.send(sender=self, user=request.user, is_updated=True if self.id else False)


来源:https://stackoverflow.com/questions/48135650/update-the-instance-after-save-using-signals-by-conditionally-refference-back-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!