It seems it is currently impossible to act on Permission creation since they are created in a post_migrate
signal (here) with the method bulk_create().
See here.
- A way to solve this would be to use create() method instead. Which I tried to do by introducing a ticket on Django ticketing system (see here) and its PR.
- The second way (which I'll use as long as
bulk_create()
is maintained for creating Permissions) is to run a method in the ready()
method (...) to assign them.
For the 2)
solution, I ended up with this :
def distribute_base_permissions():
""" This method is used to automatically grant permissions of 'base' application
to the 'Administrator' Group.
"""
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
group_content_type = ContentType.objects.get_for_model(Group)
group, created = Group.objects.get_or_create(name="Administrator")
for model in ContentType.objects.filter(app_label="base"):
for perm in Permission.objects.filter(content_type__in=[model, group_content_type]):
if (not group.has_permission(perm.codename) and
perm.codename not in model.model_class().UNUSED_PERMISSIONS):
group.add_permissions([perm])
class BaseConfig(AppConfig):
name = 'backend.base'
def ready(self):
distribute_base_permissions()
There are some flourish things in that sample that are used for my specific use case, where I'm able to install/uninstall applications during runtime according to User necessities.
My base
application is installed by default so distributing its permissions can be done like this.
For my installable applications, it's pretty much the same except that it isn't done in the ready()
method but at the end of my custom installation process :
class Application(models.Model):
class Meta:
db_table = "base_application"
verbose_name = "Application"
# ...
def migrate_post_install(self):
# ...
self.distribute_permissions()
def distribute_permissions(self):
""" This method is used to automatically grant permissions of the installed
application to the 'Administrator' Group.
"""
group, created = Group.objects.get_or_create(name="Administrator")
for model in ContentType.objects.filter(app_label=self.name):
for perm in Permission.objects.filter(content_type=model):
if (not group.has_permission(perm.codename) and
perm.codename not in model.model_class().UNUSED_PERMISSIONS):
group.add_permissions([perm])
EDIT:
The solution 1)
has been refused as it can be seen here.
A solution that is discussed would be to add a post_migrate
handler but since Permission creation is already done in a post_migrate
, I don't know how to be sure that my signal handler will be run AFTER the one that creates Permissions...
Otherwise, it seems there is in progress work to change the Permission creation process as can be seen here.