Opened 7 years ago
Last modified 7 years ago
#29386 closed Bug
Meta Inheritance for default_permissions — at Version 1
| 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 (last modified by )
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, but it affects non-proxy models as well. 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.