Actions API Reference¶
Actions represent operations that can be performed on models in django-admin-deux. They provide a flexible, composable system for creating custom functionality through mixin composition.
Action Architecture¶
Actions are built using a mixin composition pattern:
- Action Type Mixin - Defines where/how the action is triggered (List, Bulk, or Record)
- View Type Mixin - Defines which Django CBV to use (ListView, FormView, CreateView, etc.)
- BaseAction - Provides core action functionality
BaseAction¶
The foundation class for all actions.
Constructor¶
Parameters¶
- model (
type): The Django model class this action operates on - model_admin (
ModelAdmin): The ModelAdmin instance - admin_site (
AdminSite): The AdminSite instance
Raises¶
ValueError: Iflabelis not defined on the action class
Note: Actions are typically instantiated automatically by ModelAdmin. You rarely need to instantiate them directly.
Core Attributes¶
label¶
Display name for the action (shown in buttons, menus, etc.).
Type: str (required)
Example:
icon¶
Icon name or CSS class for the action button.
Type: str or None
Default: None
Example:
css_class¶
Additional CSS classes for the action button.
Type: str
Default: ''
Example:
class DeleteAction(BaseAction):
label = 'Delete'
css_class = 'danger' # Red/destructive styling
class PrimaryAction(BaseAction):
label = 'Save'
css_class = 'primary' # Primary/prominent styling
confirmation_required¶
Whether to show confirmation before executing the action.
Type: bool
Default: False
Example:
class DeleteAction(BaseAction):
label = 'Delete'
confirmation_required = True # Shows confirmation page
http_method¶
HTTP method for triggering this action.
Type: str ('GET' or 'POST')
Default: 'GET'
Example:
Permission Control (New in Milestone 5)¶
permission_class¶
Declarative permission control using the new permission system (Milestone 5).
Type: BasePermission instance or None
Default: Inherits from ModelAdmin.permission_class
Available permission classes:
- AllowAny - No restrictions
- IsAuthenticated - Requires authenticated user
- IsStaff - Requires staff status
- IsSuperuser - Requires superuser status
- HasDjangoPermission() - Checks Django model permissions
Permission composition:
from djadmin.plugins.permissions import IsStaff, HasDjangoPermission
class DeleteAction(BaseAction):
label = 'Delete'
# Both conditions must be met
permission_class = IsStaff() & HasDjangoPermission()
Example with override:
@register(Product)
class ProductAdmin(ModelAdmin):
# Default permission for all actions
permission_class = IsStaff()
# Override for specific action
list_actions = [
AddAction(permission_class=IsSuperuser()), # Only superusers can add
]
django_permission_name¶
The Django permission name used by HasDjangoPermission() to construct the full permission string.
Type: str
Default: 'view'
Common values: 'add', 'change', 'delete', 'view'
Example:
from djadmin.plugins.core.actions import AddAction
class AddAction(BaseAction):
label = 'Add'
django_permission_name = 'add' # Used to check 'app_label.add_model' permission
Note: The HasDjangoPermission() class automatically constructs the full permission string from this attribute:
- Model: Product (app: webshop)
- Action: AddAction with django_permission_name = 'add'
- Checks: webshop.add_product
Permission Methods¶
check_permission()¶
Check if user has permission to execute this action at runtime.
Parameters:
- request (HttpRequest): The HTTP request
Returns: bool - True if user has permission, False otherwise
How it works:
1. Creates a temporary view instance with PermissionMixin
2. Calls view.test_func() which evaluates the permission_class
3. Returns the result
Usage:
# Automatically called by ModelAdmin.filter_actions()
action = DeleteBulkAction(model, model_admin, site)
if action.check_permission(request):
# User can execute this action
filtered_actions.append(action)
Note: This method is called automatically by the framework. You typically don't need to call it directly.
URL Methods¶
url_name¶
Get URL name for this action.
Returns: str - URL name (e.g., 'webshop_product_export')
Example:
action = ExportAction(Product, product_admin, site)
print(action.url_name) # 'webshop_product_export'
# Use with reverse
from django.urls import reverse
url = reverse(f'admin:{action.url_name}')
action_name (property)¶
Get the normalized action name derived from the class name.
Returns: str - Normalized action name (e.g., 'edit', 'delete_bulk')
How it works:
- Uses slugify(ClassName) to convert class name to lowercase with hyphens
- Replaces hyphens with underscores
- Removes the 'action' suffix
- Example: EditAction → 'edit', DeleteBulkAction → 'delete_bulk'
Example:
class ExportAction(BaseAction):
label = 'Export'
action = ExportAction(Product, product_admin, site)
print(action.action_name) # 'export'
get_url_pattern()¶
Get URL pattern for this action.
Returns: str - URL pattern without leading slash
Default Pattern: '{app_label}/{model_name}/{action_name}/'
Note: The default pattern now uses action_name property instead of hardcoding class names. For RecordActionMixin actions, the pattern includes <int:pk>/{action_name}/.
Override to customize the URL pattern:
class AddAction(BaseAction):
label = 'Add'
def get_url_pattern(self):
opts = self.model._meta
return f'{opts.app_label}/{opts.model_name}/__new__/' # Custom pattern
View Methods¶
get_base_class()¶
Get the Django CBV base class for this action.
Returns: type - View class (e.g., FormView, CreateView)
How it works:
- Looks through the action's MRO for view-type mixins
- Returns the base_class from the first view-type mixin found
- Falls back to TemplateView if no view-type mixin is present
Example:
class MyAction(FormViewActionMixin, BaseAction):
label = 'My Action'
action = MyAction(model, admin, site)
print(action.get_base_class()) # <class 'django.views.generic.FormView'>
get_template_names()¶
Get template names as a list (Django CBV compatibility).
Returns: list[str] - List of template paths
Default Implementation: Automatically generates template paths using action_name:
1. Model-specific: 'djadmin/{app_label}/{model_name}_{action_name}.html'
2. Generic fallback: 'djadmin/actions/{action_name}.html'
Example (automatic behavior):
class EditAction(RecordActionMixin, UpdateViewActionMixin, BaseAction):
label = 'Edit'
# No need to define get_template_names() - automatic!
# Generates:
# ['djadmin/webshop/product_edit.html', 'djadmin/actions/edit.html']
Override only when you need custom template paths:
class MyAction(BaseAction):
label = 'My Action'
def get_template_names(self):
opts = self.model._meta
return [
f'djadmin/{opts.app_label}/{opts.model_name}_custom.html',
'djadmin/actions/custom_template.html',
]
Action Type Mixins¶
These mixins define where and how an action is triggered.
GeneralActionMixin¶
For actions that operate on the list view without requiring record selection.
Attributes:
- action_type = 'list'
Method to implement:
Parameters:
- request (HttpRequest): The HTTP request
- kwargs: Additional context
Returns: HttpResponse
Use cases: - Add new record - Import records - Export all records - Refresh/reload list
Example:
from djadmin.actions import BaseAction, GeneralActionMixin
from djadmin.actions.view_mixins import TemplateViewActionMixin
class ImportAction(GeneralActionMixin, TemplateViewActionMixin, BaseAction):
label = 'Import'
icon = 'upload'
def get_template_name(self):
return 'myapp/import.html'
BulkActionMixin¶
For actions that operate on multiple selected records via checkboxes.
Attributes:
- action_type = 'bulk'
Method to implement:
Parameters:
- request (HttpRequest): The HTTP request
- queryset (QuerySet): QuerySet of selected records
- kwargs: Additional context
Returns: HttpResponse
Use cases: - Delete selected records - Bulk update status - Export selected records - Bulk assign to category
Example:
from djadmin.actions import BaseAction, BulkActionMixin
from djadmin.actions.view_mixins import BulkDeleteViewActionMixin
class DeleteBulkAction(BulkActionMixin, BulkDeleteViewActionMixin, BaseAction):
label = 'Delete Selected'
icon = 'trash'
confirmation_required = True
def get_template_name(self):
return 'djadmin/actions/delete_bulk.html'
RecordActionMixin¶
For actions that operate on a single record.
Attributes:
- action_type = 'record'
Method to implement:
Parameters:
- request (HttpRequest): The HTTP request
- obj: The model instance
- kwargs: Additional context
Returns: HttpResponse
Use cases: - Edit record - Delete record - Duplicate/clone record - View record details - Download record as PDF
Example:
from djadmin.actions import BaseAction, RecordActionMixin
from djadmin.actions.view_mixins import UpdateViewActionMixin
class EditAction(RecordActionMixin, UpdateViewActionMixin, BaseAction):
label = 'Edit'
icon = 'pencil'
def get_template_name(self):
return 'djadmin/actions/edit.html'
View Type Mixins¶
These mixins define which Django CBV the action should use.
FormViewActionMixin¶
Use Django's FormView for actions with non-model forms.
Attributes:
- base_class = FormView
Use for: Actions with plain Form (not ModelForm)
Example:
from django import forms
from djadmin.actions import BaseAction, BulkActionMixin
from djadmin.actions.view_mixins import FormViewActionMixin
class StatusForm(forms.Form):
status = forms.ChoiceField(choices=[('active', 'Active'), ('inactive', 'Inactive')])
class ChangeStatusAction(BulkActionMixin, FormViewActionMixin, BaseAction):
label = 'Change Status'
def get_form_class(self):
return StatusForm
def get_template_name(self):
return 'myapp/change_status.html'
CreateViewActionMixin¶
Use Django's CreateView for creating model instances.
Attributes:
- base_class = CreateView
Use for: Creating new records with ModelForm
Example:
from djadmin.actions import BaseAction, GeneralActionMixin
from djadmin.actions.view_mixins import CreateViewActionMixin
class AddAction(GeneralActionMixin, CreateViewActionMixin, BaseAction):
label = 'Add'
icon = 'plus'
def get_template_name(self):
return 'djadmin/actions/add.html'
def get_form_class(self):
return self.model_admin.create_form_class or auto_generate_form()
UpdateViewActionMixin¶
Use Django's UpdateView for updating model instances.
Attributes:
- base_class = UpdateView
Use for: Editing existing records with ModelForm
Example:
from djadmin.actions import BaseAction, RecordActionMixin
from djadmin.actions.view_mixins import UpdateViewActionMixin
class EditAction(RecordActionMixin, UpdateViewActionMixin, BaseAction):
label = 'Edit'
icon = 'pencil'
def get_template_name(self):
return 'djadmin/actions/edit.html'
def get_form_class(self):
return self.model_admin.update_form_class or auto_generate_form()
ListActionMixin¶
Use Django's ListView for displaying lists of objects.
Attributes:
- base_class = ListView
Use for: Main list view for a model
Example:
from djadmin.actions import BaseAction
from djadmin.actions.view_mixins import ListActionMixin
class ListAction(ListActionMixin, BaseAction):
label = 'List'
def get_template_name(self):
opts = self.model._meta
return f'djadmin/{opts.app_label}/{opts.model_name}_list.html'
def get_queryset(self):
# Custom queryset logic
return self.model.objects.filter(is_active=True)
TemplateViewActionMixin¶
Use Django's TemplateView for simple template rendering.
Attributes:
- base_class = TemplateView
Use for: Actions that render templates without object/queryset
Example:
from djadmin.actions import BaseAction, GeneralActionMixin
from djadmin.actions.view_mixins import TemplateViewActionMixin
class HelpAction(GeneralActionMixin, TemplateViewActionMixin, BaseAction):
label = 'Help'
icon = 'question'
def get_template_name(self):
return 'djadmin/help.html'
DeleteViewActionMixin¶
Use Django's DeleteView for deleting single records with confirmation.
Attributes:
- base_class = DeleteView
Use for: Deleting single records
Example:
from djadmin.actions import BaseAction, RecordActionMixin
from djadmin.actions.view_mixins import DeleteViewActionMixin
class DeleteAction(RecordActionMixin, DeleteViewActionMixin, BaseAction):
label = 'Delete'
icon = 'trash'
css_class = 'danger'
confirmation_required = True
def get_template_name(self):
return 'djadmin/actions/delete.html'
def get_success_url(self):
# Redirect to list after deletion
return reverse(f'admin:{self.model_admin.list_url_name}')
BulkDeleteViewActionMixin¶
Use custom BulkDeleteView for deleting multiple records with confirmation.
Attributes:
- base_class = BulkDeleteView
Use for: Deleting multiple selected records
Example:
from djadmin.actions import BaseAction, BulkActionMixin
from djadmin.actions.view_mixins import BulkDeleteViewActionMixin
class DeleteBulkAction(BulkActionMixin, BulkDeleteViewActionMixin, BaseAction):
label = 'Delete Selected'
icon = 'trash'
confirmation_required = True
def get_template_name(self):
return 'djadmin/actions/delete_bulk.html'
def get_success_url(self):
return reverse(f'admin:{self.model_admin.list_url_name}')
RedirectViewActionMixin¶
Use Django's RedirectView for redirecting to another URL.
Attributes:
- base_class = RedirectView
Use for: Actions that redirect without displaying a view
Example:
from djadmin.actions import BaseAction, RecordActionMixin
from djadmin.actions.view_mixins import RedirectViewActionMixin
class ViewAction(RecordActionMixin, RedirectViewActionMixin, BaseAction):
label = 'View Details'
def get_redirect_url(self, request, obj):
return obj.get_absolute_url()
Action Composition Pattern¶
Actions are composed using multiple inheritance:
class MyAction(
ActionTypeMixin, # Where: List | Bulk | Record
ViewTypeMixin, # How: FormView | CreateView | ListView | etc.
BaseAction, # Core functionality
):
label = 'My Action'
# ... configuration
Built-in Action Examples¶
AddAction (List + CreateView):
class AddAction(GeneralActionMixin, CreateViewActionMixin, BaseAction):
label = 'Add'
icon = 'plus'
css_class = 'primary'
EditAction (Record + UpdateView):
class EditAction(RecordActionMixin, UpdateViewActionMixin, BaseAction):
label = 'Edit'
icon = 'pencil'
css_class = 'primary'
DeleteAction (Record + DeleteView):
class DeleteAction(RecordActionMixin, DeleteViewActionMixin, BaseAction):
label = 'Delete'
icon = 'trash'
css_class = 'danger'
confirmation_required = True
DeleteBulkAction (Bulk + BulkDeleteView):
class DeleteBulkAction(BulkActionMixin, BulkDeleteViewActionMixin, BaseAction):
label = 'Delete Selected'
icon = 'trash'
confirmation_required = True
Common Action Methods¶
These methods are commonly overridden in custom actions:
get_template_name()¶
Define which template(s) to use.
Returns: Template path or list of paths (tried in order)
Example:
def get_template_name(self):
opts = self.model._meta
return [
f'djadmin/{opts.app_label}/{opts.model_name}_export.html',
'djadmin/actions/export.html',
]
get_context_data()¶
Add custom context data to the template.
Parameters: **kwargs - Context from parent classes
Returns: dict - Template context
Example:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['export_formats'] = ['csv', 'xlsx', 'json']
return context
get_form_class()¶
Define which form class to use (for FormView/CreateView/UpdateView actions).
Returns: Form class
Example:
def get_form_class(self):
if self.model_admin.create_form_class:
return self.model_admin.create_form_class
return modelform_factory(self.model, fields='__all__')
get_queryset()¶
Define queryset for ListView/DeleteView actions.
Returns: QuerySet
Example:
def get_queryset(self):
qs = super().get_queryset()
# Filter by user permissions
if not self.request.user.is_superuser:
qs = qs.filter(owner=self.request.user)
return qs
get_success_url()¶
Define redirect URL after successful form submission.
Returns: str - URL path
Example:
def get_success_url(self):
opts = self.model._meta
return reverse(
f'admin:{opts.app_label}_{opts.model_name}_list',
current_app=self.admin_site.name,
)
Usage in ModelAdmin¶
Actions are configured in ModelAdmin through three lists:
from djadmin import ModelAdmin
from myapp.actions import ExportAction, ImportAction
class ProductAdmin(ModelAdmin):
# Actions available from list view
general_actions = [ListAction, AddAction, ExportAction, ImportAction]
# Actions for multiple selected records
bulk_actions = [DeleteBulkAction, BulkChangeStatusAction]
# Actions for single records
record_actions = [EditAction, DeleteAction, DuplicateAction]
See Also¶
- ModelAdmin API Reference - Configuring action lists
- Mixins API Reference - DjAdminViewMixin for custom views
- Custom Actions Guide - Creating custom actions
- Built-in Actions - Default CRUD actions