Opened 6 years ago

Last modified 6 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 Clayton Daley)

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.

Change History (1)

comment:1 by Clayton Daley, 6 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top