Until [#11154] is fixed, django won't create permissions for proxy models for you as it does with other models, even the one you define using the
permissions option on your models.
This snippet will make sure all permissions are create for proxy models. Just make sure this code gets loaded after the
update_contenttypes handler is registered for the
post_syncdb signal. Putting this code in one of your
INSTALLED_APPS' afterdjango.contrib.contenttypes' should do it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
import sys from django.contrib.auth.management import _get_all_permissions from django.contrib.auth.models import Permission from django.contrib.contenttypes.management import update_contenttypes from django.contrib.contenttypes.models import ContentType from django.db import models def create_proxy_permissions(app, created_models, verbosity, **kwargs): """ Creates permissions for proxy models which are not created automatically by `django.contrib.auth.management.create_permissions`. see https://code.djangoproject.com/ticket/11154 This method is inspired by `django.contrib.auth.managment.create_permissions`. Since we can't rely on `get_for_model' we must fallback to `get_by_natural_key`. However, this method doesn't automatically create missing `ContentType` so we must ensure all the model's `ContentType` are created before running this method. We do so by unregistering the `update_contenttypes` `post_syncdb` signal and calling it in here just before doing everything. """ update_contenttypes(app, created_models, verbosity, **kwargs) app_models = models.get_models(app) # This will hold the permissions we're looking for as # (content_type, (codename, name)) searched_perms = list() # The codenames and ctypes that should exist. ctypes = set() for model in app_models: opts = model._meta if opts.proxy: # We can't use `get_for_model` here since it doesn't return # the correct `ContentType` for proxy models. # see https://code.djangoproject.com/ticket/17648 app_label, model = opts.app_label, opts.object_name.lower() ctype = ContentType.objects.get_by_natural_key(app_label, model) ctypes.add(ctype) for perm in _get_all_permissions(opts): searched_perms.append((ctype, perm)) # 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.filter( content_type__in=ctypes, ).values_list( "content_type", "codename" )) objs = [ Permission(codename=codename, name=name, content_type=ctype) for ctype, (codename, name) in searched_perms if (ctype.pk, codename) not in all_perms ] Permission.objects.bulk_create(objs) if verbosity >= 2: for obj in objs: sys.stdout.write("Adding permission '%s'" % obj) models.signals.post_syncdb.connect(create_proxy_permissions) # see `create_proxy_permissions` docstring to understand why we unregister # this signal handler. models.signals.post_syncdb.disconnect(update_contenttypes)
More like this
- Serializer factory with Django Rest Framework by julio 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 6 months, 2 weeks ago
- Help text hyperlinks by sa2812 7 months, 2 weeks ago
- Stuff by NixonDash 9 months, 3 weeks ago
- Add custom fields to the built-in Group model by jmoppel 11 months, 3 weeks ago