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.
精彩评论