Django: Inherit Permissions from abstract models?
-
23-10-2019 - |
سؤال
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.