# -*- 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)) |
This comment has been minimized.
This comment has been minimized.
Agreed, thank you for this. As of 1.8, this is still an issue. This script works. In case you have no idea how to use it, try the following (I had to search around for this since I'm still learning Django):
Then you'll be able to run |
This comment has been minimized.
This comment has been minimized.
Just a heads up, if you're using Python 3, you'll have to swap out https://docs.djangoproject.com/en/1.7/ref/utils/#django.utils.encoding.smart_unicode |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I think I have this working hooked generally into post_migrate (Django 1.9 specifically, havent tested other versions, note the differences in get_models import location etc for 1.9). I have an app, label "support" which is nothing but proxy models and custom admins. In that app's models.py I added:
Worth noting I explicitly made sure 'django.contrib.contenttypes' is first in the INSTALLED_APPS list to get this working well. I was using this method https://djangosnippets.org/snippets/2677/ in Django 1.6 prior to beginning the upgrade process to go to latest stable 1.9, this is how I have worked around the proxy permissions issue in current versions. This tentatively seems to be working for me, including permission creation during test database setup etc. I may try limiting the signal to my "support" app sender explicitly but wasn't sure if other app migrations could somehow mess up content-types so, since it was already using get_or_create I simply hooked it in globally to run for all apps. Hope this helps someone! |
This comment has been minimized.
This comment has been minimized.
updated for django1.9 ` -- coding: utf-8 --"""Add permissions for proxy model. from future import unicode_literals, absolute_import, division import sys from django.contrib.auth.management import _get_all_permissions class Command(BaseCommand):
` |
This comment has been minimized.
This comment has been minimized.
For python 3 and django 1.10.x # -*- 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. """ 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.apps import apps from django.utils.encoding import smart_text class Command(BaseCommand): help = "Fix permissions for proxy models." def handle(self, *args, **options): for model in apps.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_text(opts.verbose_name_raw)}) for codename, name in _get_all_permissions(opts): 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)) |
This comment has been minimized.
This comment has been minimized.
For those of you with django-extensions installed, just call the management command Manually, or at the end of your migration script with a RunPython / call_command. |
This comment has been minimized.
This comment has been minimized.
@escsun, in |
This comment has been minimized.
This comment has been minimized.
Thank you for this! Just upgraded to django 1.10.6, and @pablocesar87 |
This comment has been minimized.
This comment has been minimized.
Here´s a working sample for django 1.11: 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.apps import apps
class Command(BaseCommand):
help = "Fix permissions for proxy models."
def handle(self, *args, **options):
for model in apps.get_models():
opts = model._meta
sys.stdout.write('{}-{}\n'.format(opts.app_label, opts.object_name.lower()))
ctype, created = ContentType.objects.get_or_create(
app_label=opts.app_label,
model=opts.object_name.lower())
for codename, name in _get_all_permissions(opts):
sys.stdout.write(' --{}\n'.format(codename))
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)) |
This comment has been minimized.
This comment has been minimized.
As this bug is still present in version 2.0 -- here is a working version for django 2.0 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) As @dckemble noticed you should adjust your INSTALLED_APPS:
|
This comment has been minimized.
This comment has been minimized.
The permissions are created for proxy models, just with the wrong from django.apps import apps
from django.contrib.auth.management import _get_all_permissions
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
def fix_proxy_permissions(**kwargs):
for model in apps.get_models():
opts = model._meta
if not opts.proxy:
continue
# The content_type creation is needed for the tests
proxy_content_type, __ = ContentType.objects.get_or_create(
app_label=opts.app_label,
model=opts.model_name,
)
concrete_content_type = ContentType.objects.get_for_model(
model,
for_concrete_model=True,
)
for code_tuple in _get_all_permissions(opts):
codename = code_tuple[0]
name = code_tuple[1]
# Delete the automatically generated permission from Django
Permission.objects.filter(
codename=codename,
content_type=concrete_content_type,
).delete()
# Create the correct permission for the proxy model
Permission.objects.get_or_create(
codename=codename,
content_type=proxy_content_type,
defaults={
'name': name,
})
signals.post_migrate.connect(fix_proxy_permissions) |
This comment has been minimized.
This comment has been minimized.
If anyone is interested, https://code.djangoproject.com/ticket/11154 has been fixed and will be part of the 2.2 release. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@arthurio I am on 2.2. While running migrations, I got:
I don't know where or how to make the rest of this truncated string show up, but it seems this 'fix' is manual, not automatic. Is that what was intended? @rebkwok I remember struggling with this once a while back. So why are all the code samples posted after your post still using name? I find this confusing. Clarification welcome.
Finally, to all and any reading this: I find the reference to "raw python" confusing. Do they mean runPython? |
This comment has been minimized.
This comment has been minimized.
@MalikRumi Checkout the 2.2.1 release notes and the related ticket. The fix should be automatic now. |
This comment has been minimized.
This comment has been minimized.
That was fast. Thanks.
*“None of you has faith until he loves for his brother or his neighbor what
he loves for himself.”*
…On Tue, Apr 30, 2019 at 3:40 PM Arthur Rio ***@***.***> wrote:
@MalikRumi <https://github.com/MalikRumi> Checkout the 2.2.1 release notes
<https://docs.djangoproject.com/en/2.2/releases/2.2.1/> and the related
ticket <https://code.djangoproject.com/ticket/30351>. The fix should be
automatic now.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://gist.github.com/7543724#gistcomment-2902383>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABJYQ6XJHNPQO2ZBGRKKMG3PTCVC7ANCNFSM4HJPHMTQ>
.
|
This comment has been minimized.
This comment has been minimized.
How to Use @wbworks |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
@mdaizovi See my comment above, this has been fixed in thee 2.2.1 release. |
This comment has been minimized.
thank you so much for this!