Permissions to Django Admin Actions
Question:
I have written some custom actions for my django project, however cannot work out how to make them available to only superusers. I have tried putting an if statement round the actions line with Users.is_superuser but it keeps giving me an error saying there is no attribute called is_superuser.
Here is my admin.py file:
from django.contrib import admin
from models import Art, Agent, UserProfile
from django.contrib import admin
from django.contrib.auth.models import Group, User, AbstractUser
from django.contrib.auth import *
from import_export import resources
from import_export.admin import ImportExportModelAdmin
#admin.site.unregister(Group)
def approve_art(modeladmin, request, queryset):
queryset.update(authenticate = "approved")
def reject_art(modeladmin, request, queryset):
queryset.update(authenticate = "rejected")
# Add in this class to customized the Admin Interface
class ArtAdmin(ImportExportModelAdmin):
list_display = ['id', 'identification', 'name', 'artist', 'category', 'type', 'agent', 'authenticate', ]
search_fields = ('name', 'category', 'artist', 'id', 'authenticate', )
actions = [approve_art, reject_art]
list_filter = ["authenticate"]
class AgentAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'phone', 'postcode', ]
search_fields = ('name', 'id', )
class ArtResource(resources.ModelResource):
class Meta:
model = Art
# Update the registeration to include this customised interface
admin.site.register(Art, ArtAdmin)
admin.site.register(Agent, AgentAdmin)
Answers:
You can override your ModelAdmin’s get_actions
method like this:
def get_actions(self, request):
actions = super(MyModelAdmin, self).get_actions(request)
if request.user.is_superuser:
actions.update(dict(youraction=youraction))
return actions
Here the documentation materials you may want to look at.
You can customize the list of actions by overriding get_actions()
. For example:
class ArtAdmin(ImportExportModelAdmin):
list_display = ['id', 'identification', 'name', 'artist', 'category', 'type', 'agent', 'authenticate', ]
search_fields = ('name', 'category', 'artist', 'id', 'authenticate', )
list_filter = ["authenticate"]
actions = [approve_art, reject_art]
def get_actions(self, request):
actions = super(ArtAdmin, self).get_actions(request)
if not request.user.is_superuser:
del actions[approve_art]
del actions[reject_art]
return actions
Check out https://docs.djangoproject.com/en/1.9/ref/contrib/admin/actions/#conditionally-enabling-or-disabling-actions for more info
Considering that an action is not ModelAdmin
-dependant, the best way to prevent it from being run by an non-authorized user remains to check it inside the action:
from django.core.exceptions import PermissionDenied
def approve_art(modeladmin, request, queryset):
if not request.user.is_superuser:
raise PermissionDenied
queryset.update(authenticate = "approved")
Which is how django handles it for the delete_selected
action.
The action would still remain available on the dropdown list though, but will return a 403 HTTP code.
Update for Django >= 2.1
https://docs.djangoproject.com/en/2.2/ref/contrib/admin/actions/#setting-permissions-for-actions
in a nutshell:
def make_published(modeladmin, request, queryset):
queryset.update(status='p')
make_published.allowed_permissions = ('change',)
or custom:
from django.contrib import admin
from django.contrib.auth import get_permission_codename
class ArticleAdmin(admin.ModelAdmin):
actions = ['make_published']
def make_published(self, request, queryset):
queryset.update(status='p')
make_published.allowed_permissions = ('publish',)
def has_publish_permission(self, request):
"""Does the user have the publish permission?"""
opts = self.opts
codename = get_permission_codename('publish', opts)
return request.user.has_perm('%s.%s' % (opts.app_label, codename))
(Example code all taken from the linked documentation.)
Only for superusers, you can display approve_art
and reject_art
admin actions by overriding get_actions() as shown below:
class ArtAdmin(ImportExportModelAdmin):
# ...
actions = ["approve_art", "reject_art"]
def get_actions(self, request):
actions = super().get_actions(request)
if not request.user.is_superuser:
del actions["approve_art"]
del actions["reject_art"]
return actions
I have written some custom actions for my django project, however cannot work out how to make them available to only superusers. I have tried putting an if statement round the actions line with Users.is_superuser but it keeps giving me an error saying there is no attribute called is_superuser.
Here is my admin.py file:
from django.contrib import admin
from models import Art, Agent, UserProfile
from django.contrib import admin
from django.contrib.auth.models import Group, User, AbstractUser
from django.contrib.auth import *
from import_export import resources
from import_export.admin import ImportExportModelAdmin
#admin.site.unregister(Group)
def approve_art(modeladmin, request, queryset):
queryset.update(authenticate = "approved")
def reject_art(modeladmin, request, queryset):
queryset.update(authenticate = "rejected")
# Add in this class to customized the Admin Interface
class ArtAdmin(ImportExportModelAdmin):
list_display = ['id', 'identification', 'name', 'artist', 'category', 'type', 'agent', 'authenticate', ]
search_fields = ('name', 'category', 'artist', 'id', 'authenticate', )
actions = [approve_art, reject_art]
list_filter = ["authenticate"]
class AgentAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'phone', 'postcode', ]
search_fields = ('name', 'id', )
class ArtResource(resources.ModelResource):
class Meta:
model = Art
# Update the registeration to include this customised interface
admin.site.register(Art, ArtAdmin)
admin.site.register(Agent, AgentAdmin)
You can override your ModelAdmin’s get_actions
method like this:
def get_actions(self, request):
actions = super(MyModelAdmin, self).get_actions(request)
if request.user.is_superuser:
actions.update(dict(youraction=youraction))
return actions
Here the documentation materials you may want to look at.
You can customize the list of actions by overriding get_actions()
. For example:
class ArtAdmin(ImportExportModelAdmin):
list_display = ['id', 'identification', 'name', 'artist', 'category', 'type', 'agent', 'authenticate', ]
search_fields = ('name', 'category', 'artist', 'id', 'authenticate', )
list_filter = ["authenticate"]
actions = [approve_art, reject_art]
def get_actions(self, request):
actions = super(ArtAdmin, self).get_actions(request)
if not request.user.is_superuser:
del actions[approve_art]
del actions[reject_art]
return actions
Check out https://docs.djangoproject.com/en/1.9/ref/contrib/admin/actions/#conditionally-enabling-or-disabling-actions for more info
Considering that an action is not ModelAdmin
-dependant, the best way to prevent it from being run by an non-authorized user remains to check it inside the action:
from django.core.exceptions import PermissionDenied
def approve_art(modeladmin, request, queryset):
if not request.user.is_superuser:
raise PermissionDenied
queryset.update(authenticate = "approved")
Which is how django handles it for the delete_selected
action.
The action would still remain available on the dropdown list though, but will return a 403 HTTP code.
Update for Django >= 2.1
https://docs.djangoproject.com/en/2.2/ref/contrib/admin/actions/#setting-permissions-for-actions
in a nutshell:
def make_published(modeladmin, request, queryset):
queryset.update(status='p')
make_published.allowed_permissions = ('change',)
or custom:
from django.contrib import admin
from django.contrib.auth import get_permission_codename
class ArticleAdmin(admin.ModelAdmin):
actions = ['make_published']
def make_published(self, request, queryset):
queryset.update(status='p')
make_published.allowed_permissions = ('publish',)
def has_publish_permission(self, request):
"""Does the user have the publish permission?"""
opts = self.opts
codename = get_permission_codename('publish', opts)
return request.user.has_perm('%s.%s' % (opts.app_label, codename))
(Example code all taken from the linked documentation.)
Only for superusers, you can display approve_art
and reject_art
admin actions by overriding get_actions() as shown below:
class ArtAdmin(ImportExportModelAdmin):
# ...
actions = ["approve_art", "reject_art"]
def get_actions(self, request):
actions = super().get_actions(request)
if not request.user.is_superuser:
del actions["approve_art"]
del actions["reject_art"]
return actions