Django Permissions Without A Model
Django Permissions without a Model#
Sometimes you will have a case where you need to add django permissions for reasons. However when your API is used to call other API’s then there won’t be a model. In that case you might want to create a dummy model - via a dummy ContentType.
You might also want to create the content type and permission in a migration.
Create an empty migrations with:
./manage.py makemigrations --empty yourappname
Then in <your_migration>.py
:
from django.db import migrations
def create_permission_class(apps, schema_editor):
Permission = apps.get_model("auth", "Permission")
ContentType = apps.get_model("contenttypes", "ContentType")
db_alias = schema_editor.connection.alias
my_content_type = ContentType.objects.using(db_alias).create(
app_label='my_content_type',
model='test'
)
create_car = Permission.objects.using(db_alias).create(
codename='create_car',
name='Create car',
content_type=my_content_type
)
def delete_permission_class(apps, schema_editor):
Permission = apps.get_model("auth", "Permission")
ContentType = apps.get_model("contenttypes", "ContentType")
db_alias = schema_editor.connection.alias
Permission.objects.using(db_alias).filter(
codename='create_car',
name='Create car'
).delete()
ContentType.objects.using(db_alias).filter(
app_label='my_content_type',
model='test'
).delete()
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.RunPython(create_permission_class, delete_permission_class),
]
Protecting a Django Rest Framework View with your Permission#
We want to use permissions.DjangoModelPermissions
however, since there is no backing model we will need to inherit from this class and change the perms_map
setting and also change the queryset
on the view.
What perms_map
looks like originally:
perms_map = {
'GET': [],
'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'],
}
First create the permission class:
from rest_framework.permissions import DjangoModelPermissions
class CreateCarModelPermissions(DjangoModelPermissions):
perms_map = {
'POST': ['my_content_type.create_car'],
}
authenticated_users_only = True
Set the view to use a sentinel queryset. Also use the permission class you just created.
queryset = User.objects.none()
Now your permissions should work - remember to give the user the permission.