Skip to content

Instantly share code, notes, and snippets.

@magopian
Created November 19, 2013 11:00
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save magopian/7543724 to your computer and use it in GitHub Desktop.
Save magopian/7543724 to your computer and use it in GitHub Desktop.
Django admin command to "fix permissions" (create them properly for proxy models). This is needed because of the following bug in Django (not fixed as of 1.6): https://code.djangoproject.com/ticket/11154
# -*- coding: utf-8 -*-
"""Add permissions for proxy model.
This is needed because of the bug https://code.djangoproject.com/ticket/11154
in Django (as of 1.6, it's not fixed).
When a permission is created for a proxy model, it actually creates if for it's
base model app_label (eg: for "article" instead of "about", for the About proxy
model).
What we need, however, is that the permission be created for the proxy model
itself, in order to have the proper entries displayed in the admin.
"""
from __future__ import unicode_literals, absolute_import, division
import sys
from django.contrib.auth.management import _get_all_permissions
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.db.models import get_models
from django.utils.encoding import smart_unicode
class Command(BaseCommand):
help = "Fix permissions for proxy models."
def handle(self, *args, **options):
for model in get_models():
opts = model._meta
ctype, created = ContentType.objects.get_or_create(
app_label=opts.app_label,
model=opts.object_name.lower(),
defaults={'name': smart_unicode(opts.verbose_name_raw)})
for codename, name in _get_all_permissions(opts, ctype):
p, created = Permission.objects.get_or_create(
codename=codename,
content_type=ctype,
defaults={'name': name})
if created:
sys.stdout.write('Adding permission {}\n'.format(p))
@peerasun
Copy link

peerasun commented Dec 11, 2019

import sys

from django.apps import apps
from django.utils.encoding import smart_text
from django.contrib.auth.management import _get_all_permissions
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

# proxy model missing permission workaround - modified for Django 2.0
def proxy_perm_create(**kwargs):
    for model in apps.get_models():
        opts = model._meta
        print(opts.verbose_name_raw)
        ctype, created = ContentType.objects.get_or_create(
            app_label=opts.app_label,
            model=opts.object_name.lower())

        for code_tupel in _get_all_permissions(opts):
            codename = code_tupel[0]
            name = code_tupel[1]
            p, created = Permission.objects.get_or_create(
                codename=codename,
                content_type=ctype,
                defaults={'name': name})
            if created:
                sys.stdout.write('Adding permission {}\n'.format(p))


models.signals.post_migrate.connect(proxy_perm_create)

How to Use @wbworks

@mdaizovi
Copy link

Does anyone have a nice solution for moving from 1.11 to 2.2 if we have done this? When my migrations were run on deployment the first time I got IntegrityError (1062, "Duplicate entry... because of django/contrib/auth/migrations/0011_update_proxy_permissions.py We didn't need those permissions anymore so I just deleted them and re ran the migration then it worked fine, but what if someone had complex groups/permissions set up...?

@arthurio
Copy link

@mdaizovi See my comment above, this has been fixed in thee 2.2.1 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment