开发者

Django: Inherit Permissions from abstract models?

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 Publish开发者_C百科Base(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.


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


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜