How to dynamically name permissions in a Django abstract model class?
I want to define some custom permissions on an abstract model class that would then be inherited by all child classes, and rather than give the permissions a generic object name that could apply to any subclassed model type, I would like to essentially use the verbose_name_plural
property of the child model as part of the permission names and description (e.g. ('view_classname', 'Can view classname')
), emulating Django's default behavior.
So, what I would be hoping to do would be something like this (which doesn't work, since verbose_name_plural
is not defined in this context):
class AbstractModel(models.Model):
class Meta:
abstract = True
permissions = (
(u'view_%ss' % verbose_name_plural, u'Can view %s' % verbose_name_plural),
)
(This problem is also described at http://code.djangoproject.com/ticket/10686, which includes a patch that implements dynamic replacement of %(class)s
in permission definitions, but this patch was never accepted and my producti开发者_高级运维on environment does not allow for patching Django.)
Could you accomplish this with a class decorator instead of an abstract model class?
def with_view_perm(cls):
vn = cls.Meta.verbose_name_plural
perms = (('view_%s' % vn, 'Can view %s' % vn),)
cls.Meta.perms += perms
return cls
@with_view_perm
class Child(models.Model):
class Meta:
verbose_name_plural = 'children'
perms = (('change_children', 'Can change children'),)
It's old - but for future reference - the desired behaviour is working out of the box now (Django 1.9)
Consider this abstract model with the appropriate permissions:
class DetailContentLifecycleClassModel (models.Model):
class Meta:
abstract=True
permissions = (
('can_change_content', 'Change content of the model'),
('can_submit_for_approval', 'Ask for final check and publishing'),
('can_publish_content', 'Publish the model as a new version'),
)
When inheriting like this:
class Test_Details (DetailContentLifecycleClassModel):
name = models.CharField(max_length=200)
class Test_Details2 (DetailContentLifecycleClassModel):
name = models.CharField(max_length=200)
The Permssions are created as following:
from playground.models import Test_Details
from django.contrib.auth.models import User, Permission
tmp = Permission.objects.filter()
Result (which is exactly what was wanted):
playground | test_ details | Can add test_ details
playground | test_ details | Change content of the model
playground | test_ details | Publish the model as a new version
playground | test_ details | Ask for final check and publishing
playground | test_ details | Can change test_ details
playground | test_ details | Can delete test_ details
playground | test_ details2 | Can add test_ details2
playground | test_ details2 | Change content of the model
playground | test_ details2 | Publish the model as a new version
playground | test_ details2 | Ask for final check and publishing
playground | test_ details2 | Can change test_ details2
playground | test_ details2 | Can delete test_ details2
The other newer way of doing this is to set default_permissions in the Meta on your base class.
Also be aware that when doing that you to make and run migrations for it to take effect.
精彩评论