It is highly recommended to read the base Django actions documentation before reading this section, since Unfold actions are derived from Django actions.
# admin.py
from django.auth.models import User
from django.contrib import admin
from django.db.models import QuerySet
from django.http import HttpRequest
from unfold.admin import ModelAdmin
from unfold.decorators import action
@admin.register(User)
class UserAdmin(ModelAdmin):
actions_list = ["custom_action"]
@action(description="Custom action", icon="person")
def custom_action(self, request: HttpRequest, queryset: QuerySet):
pass
Unfold provides two distinct ways to handle permissions for actions:
has_{permission_name}_permissionExample: has_custom_action_permission for a permission named "custom_action"
Django Built-in Permissions
app_label.permission_codenamefrom django.contrib import admin
from django.contrib.auth.models import User
from unfold.admin import ModelAdmin
from unfold.decorators import action
@admin.register(User)
class UserAdmin(ModelAdmin):
@action(
description="Custom action",
permissions=["custom_action", "auth.view_user"] # Using both permission types
)
def custom_action(self, request, queryset):
pass
def has_custom_action_permission(self, request, obj=None):
# Custom permission logic here
return request.user.is_superuser
Unfold supports custom icons for actions. Icons are supported for all actions types. You can set the icon for an action by providing icon parameter to the @action decorator.
# admin.py
from django.db.models import QuerySet
from django.http import HttpRequest
from unfold.decorators import action
@action(description="Custom action", icon="person")
def custom_action(self, request: HttpRequest, queryset: QuerySet):
pass
In Unfold it is possible to change a color of the action. Unfold supports different variants of actions. You can set the variant for an action by providing variant parameter to the @action decorator.
# admin.py
from django.db.models import QuerySet
from django.http import HttpRequest
from unfold.decorators import action
# Import ActionVariant enum from Unfold to set action variant
from unfold.enums import ActionVariant
# class ActionVariant(Enum):
# DEFAULT = "default"
# PRIMARY = "primary"
# SUCCESS = "success"
# INFO = "info"
# WARNING = "warning"
# DANGER = "danger"
@action(description="Custom action", variant=ActionVariant.PRIMARY)
def custom_action(self, request: HttpRequest, queryset: QuerySet):
pass
Besides traditional actions selected from dropdown, Unfold supports several other types of actions. Following table gives overview of all available actions together with their recommended usage:
| Type | Appearance | Usage |
|---|---|---|
| Global | Changelist - top | General actions for all instances in listing |
| Row | Changelist - each row | Action for one specific instance, executable from listing |
| Detail | Changeform - top | Action for one specific instance, executable from detail |
| Submit line | Changeform - submit line | Action performed during form submit (instance save) |
All these actions are based on custom URLs generated for each of them. Handler function for these views is basically function based view.
For actions without intermediate steps, you can write all the logic inside handler directly. Request and object ID are both passed to these action handler functions, so you are free to fetch the instance from database and perform any operations with it. In the end, it is recommended to return redirect back to either detail or listing based on where the action was triggered from.
For actions with intermediate steps, it is recommended to use handler function only to redirect to custom URL with custom view. This view can be extended from base Unfold view, to have unified experience.
By default, Django and third-party packages add their own actions, which are displayed alongside any custom actions you define. In some situations, you may want to completely hide these built-in actions, this can help save horizontal space, use different icons or texts, or move actions into a dropdown menu for a cleaner interface. To hide these default actions, set actions_list_hide_default or actions_detail_hide_default to True.
from django.utils.translation import gettext_lazy as _
from django.shortcuts import redirect
from unfold.admin import ModelAdmin
from unfold.decorators import action
class MyAdmin(ModelAdmin):
actions_list = ["my_action", "existing_action_wrapper"]
actions_list_hide_default = True
@action(description=_("History"), icon="history")
def existing_action_wrapper(self, *args, **kwargs):
# Redirect to the page URL which is created by third-party package
return redirect("https://example.com")
© 2023 - 2025 Created by unfoldadmin.com. All rights reserved.