Django: Inherit Permissions from abstract models?
Asked Answered
F

6

5

Is it possible to inherit permissions from an abstract model in Django? I can not really find anything about that. For me this doesn't work!

class PublishBase(models.Model): 
    class Meta:
        abstract = True
        get_latest_by = 'created'
        permissions = (('change_foreign_items',
                        "Can change other user's items"),)

EDIT: Not working means it fails silently. Permission is not created, as it wouldn't exist on the models inheriting from this class.

Foehn answered 3/6, 2010 at 10:13 Comment(2)
"does not work" means exactly what? can you elaborate?Yawn
See edit. and i can't find any documentation, if that is supposed to work or not...Foehn
Y
2

Here is link for resolve you issue: http://code.djangoproject.com/ticket/10686 Need to apply patch... But it realy works.

Yarborough answered 5/6, 2010 at 19:18 Comment(1)
As I get it permissions should also be inherited without this patch?(if no explicit permissions defined in children, and the %(class)s problem)Foehn
F
11

The permissions are not inherited, if the child class also defines its own class Meta. I found the following work-around, which saves from having to define the permissions again on every child model:

class AbstractBaseModel(models.Model):
    class Meta:
        abstract = True
        permissions = (("test_permission","test permission"),)


class SomeClass(AbstractBaseModel):
    name = models.CharField(max_length=255,verbose_name="Name")

    class Meta(AbstractBaseModel.Meta):
        verbose_name = ....

No need to set abstract to false in the child Meta class, since Django sets it in the parent to False when processing it! http://docs.djangoproject.com/en/dev/topics/db/models/#meta-inheritance

Foehn answered 3/6, 2010 at 10:13 Comment(2)
This is still the case in Django 1.10.5. Have applied this same workaround to get abstract permissions added to inherited models, otherwise makemigrations doesn't find the permissions.Nomi
I want to add some new permissions in inherited class. What will be correct way to go about it?Gorham
F
2

take a look at the following meta implementation, it adds read permissions to all django models that set MyModelMeta Class to be thier metaclass:

class MyModelMeta(ModelBase):
    # add a read permission to each MyModelMeta model
    def __new__(cls, name, bases, attrs):

        Meta = None

        if "Meta" in attrs:
            Meta = attrs.get("Meta")
            if hasattr(Meta, "abstract") and getattr(Meta, "abstract"):
                # if the class is abstract, don't create permissions for it, just return the class object            
                return super(MyModelMeta, cls).__new__(cls, name, bases, attrs)

        if not Meta:
            # create a new Meta Class
            Meta = type('Meta', (object,), {})

        setattr(Meta, 'permissions',(("read_%s"%name.lower(), "Can read %s"%name.lower()),))
        attrs['Meta'] = Meta
        return super(MyModelMeta, cls).__new__(cls, name, bases, attrs)        

create an abstract django models and set the meta class memeber to MyModelMeta:

class MyAbstractModel(models.Model):
    __metaclass__ = MyModelMeta

    class Meta:
        abstract=True

now, create a normal django model like so:

class SomeModel(MyAbstractModel):
    someFieldName = models.CharField(max_length=256, db_index=True)

this will generate the default add/change/delete_somemodel permissions, but also it will add a new read_somemodel permission.

if you're also using south, use this to generate the extra permissions:

from django.db.models import get_app, get_models
from django.contrib.auth.management import create_permissions

create_permissions(get_app(app), get_models(), 2 if settings.DEBUG else 0)
Faxun answered 3/6, 2010 at 10:13 Comment(0)
Y
2

Here is link for resolve you issue: http://code.djangoproject.com/ticket/10686 Need to apply patch... But it realy works.

Yarborough answered 5/6, 2010 at 19:18 Comment(1)
As I get it permissions should also be inherited without this patch?(if no explicit permissions defined in children, and the %(class)s problem)Foehn
C
2

My work-around:

class AbstractModelBase(models.base.ModelBase):

    def __new__(cls, name, bases, attrs):
        new = super(AbstractModelBase, cls).__new__(cls, name, bases, attrs)
        new._meta.permissions += (("abstract_permission", "Abstract permission"),)
        return new


class AbstractModel(models.Model):
    __metaclass__ = AbstractModelBase

    class Meta:
        abstract = True
Candiecandied answered 22/5, 2012 at 22:40 Comment(0)
Y
1

I write test for your issue. I use django 1.2.1 and i have great result!

If you want to add permission to your existing model from inherit model, every time when you change them you need to run "syncdb". Example 100% works.(in 1.2.1 without patch)

It now works.

alt text http://img203.imageshack.us/img203/7500/permn.png

Example:

from django.db import models
from django.contrib import admin

class permissions(models.Model):
    class Meta:
        abstract = True
        permissions = (("test_permission","test permission"),)


class SomeClass(permissions):
    name = models.CharField(max_length=255,verbose_name="Name")

admin.site.register(SomeClass)
Yarborough answered 5/6, 2010 at 20:25 Comment(2)
thanks, good to know that it is supposed to work like this... so i have to find out why it doesnt!Foehn
Found out what the problem is: If the child class has her own inner Meta class (that doesnt define any permissions), the permissions are not inherited!Foehn
D
0

In my case explicitly inheriting the Meta didn't work because of South. See this ticket.

django-admin.py syncdb --all fixed the problem.

Dissimilarity answered 3/12, 2013 at 21:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.