diff --git a/django_no_queryset_admin_actions/__init__.py b/django_no_queryset_admin_actions/__init__.py index fb4b8c2..40ca692 100644 --- a/django_no_queryset_admin_actions/__init__.py +++ b/django_no_queryset_admin_actions/__init__.py @@ -1 +1,2 @@ from .admin import NoQuerySetAdminActionsMixin +from .decorators import no_queryset_action diff --git a/django_no_queryset_admin_actions/decorators.py b/django_no_queryset_admin_actions/decorators.py index 4d7292b..47b92fa 100644 --- a/django_no_queryset_admin_actions/decorators.py +++ b/django_no_queryset_admin_actions/decorators.py @@ -1,23 +1,60 @@ from functools import wraps from types import FunctionType +from typing import overload + +from django.contrib.admin import ModelAdmin +from django.db.models import QuerySet +from django.http import HttpRequest NO_QUERYSET_ACTION_ATTRIBUTE = "no_queryset_action" -def no_queryset_action(action_function: FunctionType): +@overload +def no_queryset_action(function: "FunctionType") -> "FunctionType": ... + + +@overload +def no_queryset_action( + *, permissions: "list[str] | None" = None, description: "str | None" = None +) -> "FunctionType": ... + + +def no_queryset_action( + function: "FunctionType | None" = None, + *, + permissions: "list[str] | None" = None, + description: "str | None" = None, +): """ Decorator to remove `queryset` parameter from being passed to action function. """ - if getattr(action_function, NO_QUERYSET_ACTION_ATTRIBUTE, None) is not None: - return action_function + def decorator(action_function): + if getattr(action_function, NO_QUERYSET_ACTION_ATTRIBUTE, None) is not None: + return action_function + + @wraps(action_function) + def wrapper(*args): + + # Compatibility with django-admin-action-forms + modeladmin: ModelAdmin = args[0] + request: HttpRequest = args[1] + rest = [arg for arg in args[2:] if not isinstance(arg, QuerySet)] + + return action_function(modeladmin, request, *rest) + + setattr(wrapper, NO_QUERYSET_ACTION_ATTRIBUTE, True) + + if permissions is not None: + setattr(wrapper, "allowed_permissions", permissions) - @wraps(action_function) - def wrapper(*args, **kwargs): - modeladmin, request, queryset, *rest = args - return action_function(modeladmin, request, *rest, **kwargs) + if description is not None: + setattr(wrapper, "short_description", description) - setattr(wrapper, NO_QUERYSET_ACTION_ATTRIBUTE, True) + return wrapper - return wrapper + if function is None: + return decorator + else: + return decorator(function)