Skip to content

Reacting to Permission Changes with Signals

Django Guardian does not currently ship dedicated signals for permission changes. However, you can use Django's built-in post_save and post_delete signals on Guardian's permission models to react when object permissions are created or removed.

Connecting to Permission Model Signals

Guardian stores object permissions in UserObjectPermission and GroupObjectPermission models (or your custom replacements). Because these are regular Django models, you can connect to their post_save and post_delete signals just like any other model.

Wire the signals inside your AppConfig.ready() method:

from django.apps import AppConfig
from django.db.models.signals import post_save, post_delete


class MyAppConfig(AppConfig):
    name = "myapp"

    def ready(self):
        from guardian.utils import (
            get_user_obj_perms_model,
            get_group_obj_perms_model,
        )

        UserObjectPermission = get_user_obj_perms_model()
        GroupObjectPermission = get_group_obj_perms_model()
        post_save.connect(
            self.handle_perm_change,
            sender=UserObjectPermission,
            dispatch_uid="myapp.handle_perm_change.userobjectpermission.post_save",
        )
        post_save.connect(
            self.handle_perm_change,
            sender=GroupObjectPermission,
            dispatch_uid="myapp.handle_perm_change.groupobjectpermission.post_save",
        )
        post_delete.connect(
            self.handle_perm_change,
            sender=UserObjectPermission,
            dispatch_uid="myapp.handle_perm_change.userobjectpermission.post_delete",
        )
        post_delete.connect(
            self.handle_perm_change,
            sender=GroupObjectPermission,
            dispatch_uid="myapp.handle_perm_change.groupobjectpermission.post_delete",
        )

    @staticmethod
    def handle_perm_change(sender, instance, **kwargs):
        # React to the permission change here.
        # For example: invalidate a cache, write an audit log, or send a
        # notification.
        print(f"Permission changed: {instance}")

Warning

Bulk operations do not fire post_save signals. Methods like bulk_assign_perm() and assign_perm_to_many() use bulk_create() internally, so per-object post_save signals are not sent. If you rely on signals, assign permissions individually instead. See the Assign Object Permissions page for details.

Further Reading

This pattern was originally discussed in GitHub issue #805.