#29386: Meta Inheritance for default_permissions
-------------------------------+--------------------------------------
     Reporter:  Clayton Daley  |                    Owner:  nobody
         Type:  Bug            |                   Status:  new
    Component:  Uncategorized  |                  Version:  1.11
     Severity:  Normal         |               Resolution:
     Keywords:                 |             Triage Stage:  Unreviewed
    Has patch:  0              |      Needs documentation:  0
  Needs tests:  0              |  Patch needs improvement:  0
Easy pickings:  0              |                    UI/UX:  0
-------------------------------+--------------------------------------
Description changed by Clayton Daley:

Old 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.

New 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, 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.

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29386#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/070.727f7da578d27118e5e272874f304a08%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to