Proposal: Relabel permissions during contrib.auth's create_permissions post_migrate handler.

Hey folks,

Proposal: During contrib.auth’s post_migrate signal in create_permissions() to add an extra step to update permission labels? :thinking:

I’m aware there’s a ticket and a few attempts at moving managing permissions & content types to become migration operations: #29843 (Create permissions using migration operations rather than using the post_migrate signal) – Django

I haven’t looked into why these PRs didn’t progress but would it be helpful to at least support relabelling in the meantime?

If not I’m wondering whether a note in the docs may be helpful to highlight that relabelling must be done manually. The docs currently mention that creation is handled in a post migrate signal though nothing explicit about relabelling & removal is unsupported.

An initial dabble got this working for me (atm does 2 queries which can be made into 1):

--- a/django/contrib/auth/management/
+++ b/django/contrib/auth/management/
@@ -87,17 +87,13 @@ def create_permissions(
     # Find all the Permissions that have a content_type for a model we're
     # looking for.  We don't need to check for codenames since we already have
     # a list of the ones we're going to create.
-    all_perms = set(
-        Permission.objects.using(using)
-        .filter(
-            content_type__in=ctypes,
-        )
-        .values_list("content_type", "codename")
-    )
+    all_perms = Permission.objects.using(using).filter(content_type__in=ctypes)

     perms = []
     for ct, (codename, name) in searched_perms:
-        if (, codename) not in all_perms:
+        if (, codename) not in set(
+            all_perms.values_list("content_type", "codename")
+        ):
             permission = Permission()
             permission._state.db = using
             permission.codename = codename
@@ -110,6 +106,14 @@ def create_permissions(
         for perm in perms:
             print("Adding permission '%s'" % perm)

+    for ct, (codename, name) in searched_perms:
+        if (, codename, name) not in set(
+            all_perms.values_list("content_type", "codename", "name")
+        ):
+            Permission.objects.using(using).filter(
+                codename=codename, content_type=ct
+            ).update(name=name)

 def get_system_username():

(also of course folks can simply add their own post migrate and do the same… I think if this is the default behaviour then I feel it’s least astonishing)