Opened 7 years ago
Last modified 7 years ago
#29386 closed Bug
Meta Inheritance for default_permissions — at Initial Version
Reported by: | Clayton Daley | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.11 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I add Read/Browse permissions to my models that I enforce in my views. For some reason, default_permissions
isn't inheriting in the way I would expect. Nor does the Meta Inheritance section of the documentation say anything to suggest this should not be valid.
Given something like:
class BreadMetaMixin(object): # ACTION_EDIT aliases "change" for BREAD semantics, see http://paul-m-jones.com/archives/291 default_permissions = (ACTION_BROWSE, ACTION_READ, ACTION_EDIT, ACTION_ADD, ACTION_DELETE) class Encounter(AbstractParentModel): class Meta(BreadMetaMixin, AbstractParentModel.Meta): pass class Admission(Encounter): class Meta(Encounter.Meta): # also reproduced with non-proxy model proxy = True
When I makemigrations
, Encounter detects the new permissions...
... operations = [ migrations.CreateModel( name='Encounter', ... options={ 'default_permissions': ('browse', 'read', 'change', 'add', 'delete'), 'abstract': False, }, ...
but Admissions does not:
... operations = [ migrations.CreateModel( name='Admission', ... options={ 'abstract': False, 'proxy': True, # also verified with non-proxy model 'indexes': [], }, ...
It's possible that this hasn't come up because it's masked by #11154. I noticed it because I'm working around #11154 using a migration like:
def add_proxy_permissions(apps, schema_editor): """Workaround https://code.djangoproject.com/ticket/11154 by manually creating the required permissions.""" ContentType = apps.get_model('contenttypes', 'ContentType') Permission = apps.get_model('auth', 'Permission') for model in ['Admission']: class_ = apps.get_model('task_manager', model) content_type = ContentType.objects.get_for_model(class_, for_concrete_model=False) for perm in class_._meta.default_permissions: Permission.objects.get_or_create( content_type=content_type, codename='{}_{}'.format(perm, model.lower()), )
This works great on two meta models where BreadMetaMixin
is included directly (e.g. UserProxy
wraps auth.models.User
and includes BreadMetaMixin
). When I moved the code over to Admission
, however, it wasn't working correctly. If I mixin BreadMetaMixin
directly, it works fine so I've narrowed it down to a Meta Inheritance issue.