You have seen actions in Django admin already. Those are options in the dropdown on the change list:
Let's make two actions for our Category model: one to enable and another to disable a category.
We have this Category model:
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True)
is_active = models.BooleanField(default=True, db_index=True)
Open admin.py
, we have a basic ModelAdmin
for it there:
class CategoryAdmin(admin.ModelAdmin):
list_display = (
"name",
"slug",
"is_active",
"id",
)
admin.site.register(Category, CategoryAdmin)
There are two ways we can add actions:
- define an action within the ModelAdmin
class and it only be used here
- define an action outside any ModelAdmin
class and it will be possible to reuse it in other ModelAdmin
classes.
Let's try both.
Defining a Django Admin Action within a ModelAdmin class¶
class CategoryAdmin(admin.ModelAdmin):
list_display = (
"name",
"slug",
"is_active",
"id",
)
actions = [
"make_inactive",
]
@admin.action(description="Deactivate selected categories")
def make_inactive(self, request, queryset):
for category in queryset:
category.is_active = False
category.save()
admin.site.register(Category, CategoryAdmin)
What we did here is this:
- add a method to CategoryAdmin
called make_inactive
decorated by @admin.action
- add the actions
attribute to the CategoryAdmin
where we specify the action as a string. Specifying it as a string tells Django to this actions as a method.
Defining Django Admin Action outside a ModelAdmin
¶
This approach allows you to define actions in a way that they can be reused by other ModelAdmin
instances.
Marking active/inactive is a great example of a Django Admin Action for such reusability.
def make_active(modeladmin, request, queryset):
for obj in queryset:
obj.is_active = True
obj.save()
make_active.short_description = "Activate selected %(verbose_name_plural)s"
class CategoryAdmin(admin.ModelAdmin):
list_display = (
"name",
"slug",
"is_active",
"id",
)
actions = [
"make_inactive",
make_active,
]
@admin.action(description="Deactivate selected categories")
def make_inactive(self, request, queryset):
for category in queryset:
category.is_active = False
category.save()
admin.site.register(Category, CategoryAdmin)
Now our Django admin actions for our Category page looks like this:
You can now add make_active
to actions of other ModelAdmin
classes.
Pay attention to this line:
make_active.short_description = "Activate selected %(verbose_name_plural)s"
From Django Docs:
Action descriptions are %-formatted and may contain '%(verbose_name)s' and '%(verbose_name_plural)s' placeholders, which are replaced, respectively, by the model’s verbose_name and verbose_name_plural.
Read more in Django Admin Actions Documentation