Reputation: 169
I was trying to create a custom permission in a migration, however after running migrate, the permission was not created in the permission table. Could someone point out what the error was? Also I am not sure what I should use as the related model for ContentType as the permission is used for restricting users that can view a page which shows summary of users on the site. Any help will be greatly appreciated, thanks.
def add_view_aggregated_data_permissions(apps, schema_editor):
ContentType = apps.get_model('django', 'ContentType')
Permission = apps.get_model('auth', 'Permission')
content_type = ContentType.objects.get(app_label='auth', model='user')
permission = Permission.objects.create(codename='can_view_data',
name='Can view data',
content_type=content_type)
Upvotes: 4
Views: 5030
Reputation: 766
I wanted to created a custom permission (read) for all app models. I did this two steps:
Create an extended permission from DjangoModelPermissions:
class DjangoModelPermissionsExtended(DjangoModelPermissions):
"""
"""
perms_map = {
'GET': ['%(app_label)s.read_%(model_name)s'],
'OPTIONS': [],
'HEAD': [],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
Put it in each view I want to have read permission:
class ExampleViewSet(viewsets.ModelViewSet):
permission_classes = (
DjangoModelPermissionsExtended,
)
Create a django command customread.py:
from django.core.management.base import BaseCommand, CommandError
from project.app import models as app_models
from django.db import models
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
import inspect
class Command(BaseCommand):
help = 'Create the read permission to app models'
def handle(self, *args, **options):
for name, obj in inspect.getmembers(app_models):
if inspect.isclass(obj) and issubclass(obj, models.Model):
try:
self.add_canread(obj)
self.stdout.write(self.style.SUCCESS(
'created permission for %s' % obj
))
except Exception as e:
self.stdout.write(self.style.ERROR(
'Permission already exists for %s' % obj
))
def add_canread(self, object_class):
"""This a function that can be executed in order to create
new permissions (read view) to a class in DB.
"""
if inspect.isclass(object_class):
content_type = ContentType.objects.get_for_model(object_class)
permission = Permission.objects.create(
codename='read_{}'.format(object_class._meta.model_name),
name='Can view {}'.format(object_class.__name__),
content_type=content_type,
)
else:
msg = "The object is not a class"
print(msg)
Execute it after doing migrations:
python manage.py customread
Upvotes: 1
Reputation: 2521
As of django 1.8 and built-in migrations this is very painless.
Run makemigration
./manage.py makemigrations
run the migration created in the step above
./manage.py migrate
Upvotes: 0
Reputation: 19902
I would recommend you to use the standard way to use custom permissions as described in the Django documentation. You will avoid many issues altogether.
To create custom permissions for a given model object, use the permissions model Meta attribute.
This example model creates a custom permission:
class MyModel(models.Model):
...
class Meta:
permissions = (
('view_data', "Can see available data"),
)
The only thing this does is create those extra permissions when you run
manage.py migrate
. Your code is in charge of checking the value of these permissions when a user is trying to access the functionality provided by the application...
Then you can use the permission_required
decorator with your view to check for the specific permission:
from django.contrib.auth.decorators import permission_required
@permission_required('myapp.view_data')
def my_view(request):
...
Upvotes: 5