diff options
| author | Nick Pope <nick.pope@flightdataservices.com> | 2021-01-13 16:19:22 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-13 17:19:22 +0100 |
| commit | 920448539631b52dcee53bd32a880abbc9de18bd (patch) | |
| tree | 03dd52fd206088302de11e0b485b420726718a4a /django | |
| parent | 83fcfc9ec8610540948815e127101f1206562ead (diff) | |
Fixed #16117 -- Added decorators for admin action and display functions.
Refs #25134, #32099.
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/admin/__init__.py | 10 | ||||
| -rw-r--r-- | django/contrib/admin/actions.py | 9 | ||||
| -rw-r--r-- | django/contrib/admin/decorators.py | 73 | ||||
| -rw-r--r-- | django/contrib/admin/options.py | 3 |
4 files changed, 85 insertions, 10 deletions
diff --git a/django/contrib/admin/__init__.py b/django/contrib/admin/__init__.py index 0bcee1a578..975cf053aa 100644 --- a/django/contrib/admin/__init__.py +++ b/django/contrib/admin/__init__.py @@ -1,4 +1,4 @@ -from django.contrib.admin.decorators import register +from django.contrib.admin.decorators import action, display, register from django.contrib.admin.filters import ( AllValuesFieldListFilter, BooleanFieldListFilter, ChoicesFieldListFilter, DateFieldListFilter, EmptyFieldListFilter, FieldListFilter, ListFilter, @@ -11,10 +11,10 @@ from django.contrib.admin.sites import AdminSite, site from django.utils.module_loading import autodiscover_modules __all__ = [ - "register", "ModelAdmin", "HORIZONTAL", "VERTICAL", "StackedInline", - "TabularInline", "AdminSite", "site", "ListFilter", "SimpleListFilter", - "FieldListFilter", "BooleanFieldListFilter", "RelatedFieldListFilter", - "ChoicesFieldListFilter", "DateFieldListFilter", + "action", "display", "register", "ModelAdmin", "HORIZONTAL", "VERTICAL", + "StackedInline", "TabularInline", "AdminSite", "site", "ListFilter", + "SimpleListFilter", "FieldListFilter", "BooleanFieldListFilter", + "RelatedFieldListFilter", "ChoicesFieldListFilter", "DateFieldListFilter", "AllValuesFieldListFilter", "EmptyFieldListFilter", "RelatedOnlyFieldListFilter", "autodiscover", ] diff --git a/django/contrib/admin/actions.py b/django/contrib/admin/actions.py index 1e1c3bd384..665d83c7f7 100644 --- a/django/contrib/admin/actions.py +++ b/django/contrib/admin/actions.py @@ -4,12 +4,17 @@ Built-in, globally-available admin actions. from django.contrib import messages from django.contrib.admin import helpers +from django.contrib.admin.decorators import action from django.contrib.admin.utils import model_ngettext from django.core.exceptions import PermissionDenied from django.template.response import TemplateResponse from django.utils.translation import gettext as _, gettext_lazy +@action( + permissions=['delete'], + description=gettext_lazy('Delete selected %(verbose_name_plural)s'), +) def delete_selected(modeladmin, request, queryset): """ Default action which deletes the selected objects. @@ -73,7 +78,3 @@ def delete_selected(modeladmin, request, queryset): "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context) - - -delete_selected.allowed_permissions = ('delete',) -delete_selected.short_description = gettext_lazy("Delete selected %(verbose_name_plural)s") diff --git a/django/contrib/admin/decorators.py b/django/contrib/admin/decorators.py index 1c43c9505c..4de99580ad 100644 --- a/django/contrib/admin/decorators.py +++ b/django/contrib/admin/decorators.py @@ -1,3 +1,76 @@ +def action(function=None, *, permissions=None, description=None): + """ + Conveniently add attributes to an action function:: + + @admin.action( + permissions=['publish'], + description='Mark selected stories as published', + ) + def make_published(self, request, queryset): + queryset.update(status='p') + + This is equivalent to setting some attributes (with the original, longer + names) on the function directly:: + + def make_published(self, request, queryset): + queryset.update(status='p') + make_published.allowed_permissions = ['publish'] + make_published.short_description = 'Mark selected stories as published' + """ + def decorator(func): + if permissions is not None: + func.allowed_permissions = permissions + if description is not None: + func.short_description = description + return func + if function is None: + return decorator + else: + return decorator(function) + + +def display(function=None, *, boolean=None, ordering=None, description=None, empty_value=None): + """ + Conveniently add attributes to a display function:: + + @admin.display( + boolean=True, + ordering='-publish_date', + description='Is Published?', + ) + def is_published(self, obj): + return obj.publish_date is not None + + This is equivalent to setting some attributes (with the original, longer + names) on the function directly:: + + def is_published(self, obj): + return obj.publish_date is not None + is_published.boolean = True + is_published.admin_order_field = '-publish_date' + is_published.short_description = 'Is Published?' + """ + def decorator(func): + if boolean is not None and empty_value is not None: + raise ValueError( + 'The boolean and empty_value arguments to the @display ' + 'decorator are mutually exclusive.' + ) + if boolean is not None: + func.boolean = boolean + if ordering is not None: + func.admin_order_field = ordering + if description is not None: + func.short_description = description + if empty_value is not None: + func.empty_value_display = empty_value + return func + if function is None: + return decorator + else: + return decorator(function) + + def register(*models, site=None): """ Register the given model(s) classes and wrapped ModelAdmin class with diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 5214a266e3..6b0982eab8 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -12,6 +12,7 @@ from django.contrib.admin import helpers, widgets from django.contrib.admin.checks import ( BaseModelAdminChecks, InlineModelAdminChecks, ModelAdminChecks, ) +from django.contrib.admin.decorators import display from django.contrib.admin.exceptions import DisallowedModelAdminToField from django.contrib.admin.templatetags.admin_urls import add_preserved_filters from django.contrib.admin.utils import ( @@ -848,12 +849,12 @@ class ModelAdmin(BaseModelAdmin): action_flag=DELETION, ) + @display(description=mark_safe('<input type="checkbox" id="action-toggle">')) def action_checkbox(self, obj): """ A list_display column containing a checkbox widget. """ return helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME, str(obj.pk)) - action_checkbox.short_description = mark_safe('<input type="checkbox" id="action-toggle">') @staticmethod def _get_action_description(func, name): |
