سؤال

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.

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

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

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

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)

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)

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top