Skip to content

ModelAdmin

ModelAdmin

djadmin.options.ModelAdmin

Encapsulates all admin options and functionality for a model.

ModelAdmin is the central configuration point for how a model is displayed and interacted with in the admin interface. It controls list views, forms, actions, and permissions.

Class Attributes

Attribute Type Description
list_display list Fields/columns to display in list view. Type: list[str | Callable | Column] | None Default: None (initialized to [Column('__str__')])
general_actions list Actions available without record selection. Type: list[type[BaseAction]] | None Default: None (uses plugin defaults: [ListAction, AddAction])
bulk_actions list Actions that operate on multiple selected records. Type: list[type[BaseAction]] | None Default: None (uses plugin defaults: [DeleteBulkAction])
record_actions list Actions that operate on a single record. Type: list[type[BaseAction]] | None Default: None (uses plugin defaults: [EditAction, DeleteAction])
paginate_by int Records per page in list view. Default: 100
pagination_class type Custom pagination class. Default: None
permission_class - Permission checker for the ModelAdmin. Default: IsStaff() & HasDjangoPermission()
form_class type Base form class for create/update views. Type: type[ModelForm] | None. Default: None (auto-generates form)
fields list Base field list for forms. Type: list[str] | Literal['__all__']. Default: '__all__'
create_form_class type Form class for creating records. Overrides form_class. Default: None
create_fields list Field list for create forms. Overrides fields. Default: None
update_form_class type Form class for updating records. Overrides form_class. Default: None
update_fields list Field list for update forms. Overrides fields. Default: None
search_fields list Fields to search. Triggers 'search' feature.
list_filter list Fields to filter by. Triggers 'filter' feature.
ordering list Default ordering. Triggers 'ordering' feature.

Examples

Basic registration::

from djadmin import ModelAdmin, register

@register(Product)
class ProductAdmin(ModelAdmin):
    list_display = ['name', 'sku', 'price']
    paginate_by = 50

With Column configuration::

from djadmin import ModelAdmin, register, Column

@register(Product)
class ProductAdmin(ModelAdmin):
    list_display = [
        Column('name'),
        Column('sku', label='SKU Code', classes='font-mono'),
        Column('price', empty_value='N/A'),
    ]

Different fields for create vs update::

@register(Product)
class ProductAdmin(ModelAdmin):
    create_fields = ['name', 'sku', 'price']
    update_fields = ['name', 'price', 'description', 'status']

Custom form class::

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = '__all__'
        widgets = {
            'description': forms.Textarea(attrs={'rows': 5}),
        }

@register(Product)
class ProductAdmin(ModelAdmin):
    form_class = ProductForm

Custom actions::

from djadmin.actions import BaseAction, GeneralActionMixin

class ExportAction(GeneralActionMixin, BaseAction):
    label = 'Export'
    icon = 'download'

@register(Product)
class ProductAdmin(ModelAdmin):
    general_actions = [ListAction, AddAction, ExportAction]

Notes

  • ModelAdmin instances are created automatically by AdminSite.register()
  • You rarely need to instantiate ModelAdmin directly
  • Feature indicators trigger plugin requirements at startup
  • Form/fields resolution: create_form_class or form_class or auto-generated

Method Resolution Order

  1. djadmin.options.ModelAdmin

Attributes

Attribute Value Defined in
FEATURE_INDICATORS {'search': ['search_fields'], 'filter': ['list_filter'], ... djadmin.options.ModelAdmin
__annotations__ {'list_display': 'list[str | Callable | Column] | None', ... djadmin.options.ModelAdmin
bulk_actions None djadmin.options.ModelAdmin
create_fields None djadmin.options.ModelAdmin
create_fieldsets None djadmin.options.ModelAdmin
create_form_class None djadmin.options.ModelAdmin
create_layout None djadmin.options.ModelAdmin
create_view_class None djadmin.options.ModelAdmin
detail_view_class None djadmin.options.ModelAdmin
fields __all__ djadmin.options.ModelAdmin
form_class None djadmin.options.ModelAdmin
general_actions None djadmin.options.ModelAdmin
inline_sortable False djadmin.options.ModelAdmin
inlines None djadmin.options.ModelAdmin
list_display None djadmin.options.ModelAdmin
list_filter None djadmin.options.ModelAdmin
list_view_class None djadmin.options.ModelAdmin
model None djadmin.options.ModelAdmin
order_fields None djadmin.options.ModelAdmin
ordering None djadmin.options.ModelAdmin
paginate_by 100 djadmin.options.ModelAdmin
pagination_class None djadmin.options.ModelAdmin
permission_class <djadmin.plugins.permissions.operators.And object at 0x7e... djadmin.options.ModelAdmin
record_actions None djadmin.options.ModelAdmin
search_fields None djadmin.options.ModelAdmin
update_fields None djadmin.options.ModelAdmin
update_fieldsets None djadmin.options.ModelAdmin
update_form_class None djadmin.options.ModelAdmin
update_layout None djadmin.options.ModelAdmin

Methods

__init__(self, model, admin_site: 'AdminSite')

Defined in: <class 'djadmin.options.ModelAdmin'>

Initialize the ModelAdmin.

Args: model: The Django model class this admin is managing. admin_site: The AdminSite instance this admin is registered to.

Notes: - ModelAdmin instances are typically created automatically by AdminSite.register() or the @register decorator - You rarely need to instantiate ModelAdmin directly

Source code in options.py line 367
    def __init__(self, model, admin_site: AdminSite):
        """Initialize the ModelAdmin.

        Args:
            model: The Django model class this admin is managing.
            admin_site: The AdminSite instance this admin is registered to.

        Notes:
            - ModelAdmin instances are typically created automatically by
              AdminSite.register() or the @register decorator
            - You rarely need to instantiate ModelAdmin directly
        """
        self.model = model
        self.admin_site = admin_site

        # Initialize list_display if not set
        if self.list_display is None:
            self.list_display = [Column('__str__')]

        # Process inlines (converts Django-style inlines to Collections)
        self._process_inlines_to_layout()

        # Initialize and instantiate action classes
        self._initialize_actions()

__repr__(self)

Defined in: <class 'djadmin.options.ModelAdmin'>

Source code in repr.py line 37
        def __repr__(self):
            return _generate_repr(self)

filter_actions(self, actions, request, obj=None)

Defined in: <class 'djadmin.options.ModelAdmin'>

Filter actions based on user permissions, with request-level caching.

Uses the action's check_permission() method to determine if the user has permission to execute each action. Results are cached per request to avoid redundant permission checks.

Performance Impact: Without caching: Actions filtered multiple times per request With caching: Actions filtered once per request/object combination

Args: actions: List of action instances request: The HTTP request with user information obj: Optional specific object instance for object-level permissions

Returns: List of actions that the user has permission to execute

Source code in options.py line 596
    def filter_actions(self, actions, request, obj=None):
        """
        Filter actions based on user permissions, with request-level caching.

        Uses the action's check_permission() method to determine if
        the user has permission to execute each action. Results are
        cached per request to avoid redundant permission checks.

        Performance Impact:
            Without caching: Actions filtered multiple times per request
            With caching: Actions filtered once per request/object combination

        Args:
            actions: List of action instances
            request: The HTTP request with user information
            obj: Optional specific object instance for object-level permissions

        Returns:
            List of actions that the user has permission to execute
        """
        if not actions:
            return []

        # Use request identity and object PK as cache key
        # This ensures cache is isolated per request and per object
        cache_key = (id(request), obj.pk if obj else None)

        # Create cached filter function with limited cache size
        @lru_cache(maxsize=128)
        def _cached_filter(key):
            return [action for action in actions if action.check_permission(request, obj=obj)]

        return _cached_filter(cache_key)

list_url_name @property

Defined in: <class 'djadmin.options.ModelAdmin'>

Get URL name for list view (without namespace)

opts @property

Defined in: <class 'djadmin.options.ModelAdmin'>

Shortcut to model._meta

requested_features @property

Defined in: <class 'djadmin.options.ModelAdmin'>

Get set of features requested by checking indicator attributes and column configuration.

Checks both legacy attributes (list_filter, search_fields, etc.) and column-centric configuration (Column.filter, Column.order).

Also checks Layout API features (collections, conditional_fields, computed_fields).

Fields

Field Type Related To
__dict__ getset_descriptor -
__weakref__ getset_descriptor -