From e1fd42c4f8195494a68d16c9e665cae0c7cf3055 Mon Sep 17 00:00:00 2001 From: Marcelo Galigniana Date: Sun, 14 Jul 2024 23:57:54 -0300 Subject: [PATCH] Made changes asked in review by sarahboyce: - Action gets queryset of 1 object as param when is change view - Add permissions test - Add documentation --- django/contrib/admin/options.py | 18 +++++- .../contrib/admin/templatetags/admin_urls.py | 11 ---- ...-actions-to-the-modeladmin-detail-view.png | Bin 0 -> 44118 bytes docs/ref/contrib/admin/actions.txt | 18 ++++++ tests/admin_views/admin.py | 19 ++++-- tests/admin_views/test_actions.py | 58 +++++++++++++++--- 6 files changed, 97 insertions(+), 27 deletions(-) create mode 100644 docs/ref/contrib/admin/_images/adding-actions-to-the-modeladmin-detail-view.png diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 9565cbc24d..9961ddd729 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -1681,7 +1681,16 @@ class ModelAdmin(BaseModelAdmin): if isinstance(response, HttpResponseBase): return response else: - return HttpResponseRedirect(request.get_full_path()) + # If action was executed from change view, redirect to + # list view once finished. + return HttpResponseRedirect( + request.get_full_path() + if not change + else reverse( + "admin:%s_%s_changelist" + % (self.opts.app_label, self.opts.model_name) + ) + ) else: msg = _("No action selected.") self.message_user(request, msg, messages.WARNING) @@ -1873,12 +1882,15 @@ class ModelAdmin(BaseModelAdmin): if request.method == "POST": if actions and request.POST.get("action", ""): action_failed = False - response = self.response_action(request, obj, change=not add) + response = self.response_action( + request, + self.get_queryset(request).filter(id=object_id), + change=not add, + ) if response: return response else: action_failed = True - if action_failed: # Redirect back to the changelist page to avoid resubmitting the # form if the user refreshes the browser or uses the "No, take diff --git a/django/contrib/admin/templatetags/admin_urls.py b/django/contrib/admin/templatetags/admin_urls.py index c1f9e10752..8ee7a8ff5e 100644 --- a/django/contrib/admin/templatetags/admin_urls.py +++ b/django/contrib/admin/templatetags/admin_urls.py @@ -86,14 +86,3 @@ def admin_actions_tag(parser, token): return InclusionAdminNode( parser, token, func=admin_actions, template_name="actions.html" ) - - -@register.tag(name="change_list_object_tools") -def change_list_object_tools_tag(parser, token): - """Display the row of change list object tools.""" - return InclusionAdminNode( - parser, - token, - func=lambda context: context, - template_name="change_list_object_tools.html", - ) diff --git a/docs/ref/contrib/admin/_images/adding-actions-to-the-modeladmin-detail-view.png b/docs/ref/contrib/admin/_images/adding-actions-to-the-modeladmin-detail-view.png new file mode 100644 index 0000000000000000000000000000000000000000..d2452e67280a2c2069f844e11aa035259e25a161 GIT binary patch literal 44118 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 NiDO5JKY^MT zx9kI`si3^nsaVM&T5X<=0EkJM3R{-OvALD^^K}xGuA0y;n%=@%ZOyEwo+_>wK0OrKz-#{fYShlEb+-{Eim5uGmKK9b2%8OmH9V%n z@Ag)VI&F$Cq=UY2KHNUPlF}1Cm_~3rBpFk4X{EIYRO^g8I6ryLlCc=euf07|ul$k) z7HJOWypvlHiX2$)?Q^BJKFiQ8vp(g_D z(DC^VCd0J3@aeou*Vo~Lu(U)y&?N(h68({=3Pv<|jn$A)ZXUGUTZ&P(pH5e8Zq3NO zV%df;*$TZ&W-mjRbkXEK`g!8!7^ZHe>_kurOr*5di?8XfqtuC>x`}jmm`RX&Ms&-m zp{T61+~lT4X7PmBX63T9y?Y-@R30O5ZSmZzgK?C~p3w4-oFbF9bI2_Nq-GVTyspGl z!2;5bxTTAF={;gcAj%zqZaL+p3OaM zh|G_R=W)1`qm?E=7wheO7d#|Fng0@O`?W1YcBOYX&P#iH2)KY3AZ9XdlYdURf7-3E^N*3c$h{WYLdSj0 z7*ODB!q~#@sie9N7_?40N&E67uP+&irgTWEjUeQk>YFN`yfoLf$X+HhU&Tow*)rwm zk2T<=NNoA*%BIT1mwscEYZA5GMt>PhaEbrq56He$^XaatG(}ZM5yhx3{|UK^zVNDC z_8HiblLVbf1lrg4(c&F_hqcHS&v4Y3R|r$7pJ8duJqE**b)F{?ZBLX9PvR**|* zCA=tEr+c3-Bw=(XtcosFfb}#QvWnQE)QY2x@=8z<8se71 zF7)uL%A>azuF6}h;~AAG(O zvQC%s75gaT?uBg2K${CEQ1j^TxWF!72EQCjq7Z(wiPa3s%<6TQ0fH+dWnqbgkl^HO;8+tgLg_vo4@U z)n>-zC$TEM1LJ;~O+E`kG98l_kZD5;>Dx~cIcq(yg;)%PAZ%bmYHlX?TPR6pHLnvR zWNjy8`H{U|;li5+g2?zjAop}K|EQ>z1u%t~n3QO5!>Ep_Uv5yTn_8LMvp+7YX`GumlqQd+~aASqknrfA6NcU#i08oAtH4y;R}r4RpgkGJ%dd zZ{!j+q)2v|M4!no|Y&dGFg#f@%ZH8_bD0S-Y99Uw_WkC>H=t*y}) zru@i6u}mZfT=RLM4i%a&YO2uPh>X|LZlU+^_4S;GW~odR>%80?JmqL3=B=4Q+M-5H zAfrL;Ww}5#j<&Jbk9Ir@+BR*w;`_X1svHK3`c0FjZvQ520D&XF3QTev`l%udT#jD9 zS>8yr>^5X`=uh23W_`KynX%|!betdxF2Lk-ckJ8B*U=*hq0zM6!{lt#b6M~z{C;5b zBFx*F-^1zhNALMWo7iQjo6SE=<-U}t8#52pz@nv9fgFw<4lmd5yt@y66#-)^b?f4cVVbybK>-&!~ zF;m9t+aIFae|N?^$EVB$+V>7fKp8#F`LLb~fnP!!x1=;sgBoh9*xC7U_nNw$8grf5 zQq;(cc!|r?#_b#lWg{b;ex_nb^yU+PIVlPn=2Dx#OKn`oXaP`%$U3)w;lapB9>ZzL z#)|clA2*x#%}{&imhl05KzudaV(`|6^Q-sOTL1aDOC3cZM;cv(Jr!%`mOptLazvB)RiU+vXcNJ)u9MR?@js(IiIl0~Yo3*1|-_`Ne z&5UPSuBb8Ql!4y|oUi)dr4fI<+I>Pu{9mcI|19#pF(4d|vOo099aBFXU;yC=ESFpl z1${?$U-ekrL%${1twMuiG!UC$F~|E`L*5>LF8oKAmS$>Ha%t51w} zmn&uA5&inVb?I0D1}L^@P_13pPd*i5^*`v|SU}qcip-ciT@cjym^b;XlEM6{1Yi%~ z99=^b;4O+lEB<_dyOH*Ag!+$`zl#pM{^kj+q~F5xU8?gw<=`nJw{3zosPTz4X^dGe zddg^YPE-A);Su1mG&ByhF=vwCRS~E_?|}$4x116{Uk_nL4U;+Dnbe$uA3AufscLY5 z*j,lPKX-nbNTKZTX=DY-k^;UYldAClC-hR#|?aqbp(Q!Bn_e-M3=3g4XST$24H zXBh1mv&BQQv@{47hX3g>Kkl#o?Wr&w@gL8}{f{aCU+hLL#%yJBviR}i#~XM58pCe+ zo&m<4cO4xaK*`LS;(33gCrg~a^HzW_oCo^41ANTo#wUmSmgSp)HjS?8QhynNcB`;Q z1~6L~tK%$$LSW|z+2vJMMw^>}JQ=`9Vh@L#I{w>G=BEv84xq!l9pLi;K5mR$xeFjN zZ%bc1gz`K)Qpzb52ies4!hgeJpVW8lOS7}*(^b literal 0 HcmV?d00001 diff --git a/docs/ref/contrib/admin/actions.txt b/docs/ref/contrib/admin/actions.txt index 263d43f8a3..23b3c2a6b3 100644 --- a/docs/ref/contrib/admin/actions.txt +++ b/docs/ref/contrib/admin/actions.txt @@ -149,6 +149,24 @@ That code will give us an admin change list that looks something like this: .. image:: _images/adding-actions-to-the-modeladmin.png +The actions will be available also in the detail view but the description should be +adjusted to make sense we are talking about only one object:: + + @admin.action( + description="Mark selected story as published", + description_plural="Mark selected stories as published", + ) + def make_published(modeladmin, request, queryset): + pass + +It will looks like this: + +.. image:: _images/adding-actions-to-the-modeladmin-detail-view.png + +.. note:: + + In this case ``queryset`` will be a :class:`~django.db.models.query.QuerySet` of one object. + That's really all there is to it! If you're itching to write your own actions, you now know enough to get started. The rest of this document covers more advanced techniques. diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index 1fd76b5c52..9bb6d4b3a5 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -6,6 +6,7 @@ from django import forms from django.contrib import admin from django.contrib.admin import BooleanFieldListFilter from django.contrib.admin.views.main import ChangeList +from django.contrib.auth import get_permission_codename from django.contrib.auth.admin import GroupAdmin, UserAdmin from django.contrib.auth.models import Group, User from django.core.exceptions import ValidationError @@ -416,11 +417,10 @@ def redirect_to(modeladmin, request, selected): description_plural="Download selected subscriptions", ) def download(modeladmin, request, selected): - from django.db.models.query import QuerySet - - if isinstance(selected, QuerySet): + if selected.count() > 1: buf = StringIO("This is the content of the file") else: + selected = selected.get() buf = StringIO(f"This is the content of the file written by {selected.name}") return StreamingHttpResponse(FileWrapper(buf)) @@ -431,8 +431,19 @@ def no_perm(modeladmin, request, selected): return HttpResponse(content="No permission to perform this action", status=403) +@admin.action(permissions=["custom"]) +def custom_action(modeladmin, request, selected): + return HttpResponse(content="OK", status=200) + + class ExternalSubscriberAdmin(admin.ModelAdmin): - actions = [redirect_to, external_mail, download, no_perm] + actions = [redirect_to, external_mail, download, no_perm, custom_action] + + def has_custom_permission(self, request): + """Does the user have the custom permission?""" + opts = self.opts + codename = get_permission_codename("custom", opts) + return request.user.has_perm("%s.%s" % (opts.app_label, codename)) class PodcastAdmin(admin.ModelAdmin): diff --git a/tests/admin_views/test_actions.py b/tests/admin_views/test_actions.py index 809a0a8261..77a67b0e6e 100644 --- a/tests/admin_views/test_actions.py +++ b/tests/admin_views/test_actions.py @@ -3,6 +3,7 @@ import json from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME from django.contrib.admin.views.main import IS_POPUP_VAR from django.contrib.auth.models import Permission, User +from django.contrib.contenttypes.models import ContentType from django.core import mail from django.db import connection from django.template.loader import render_to_string @@ -269,7 +270,9 @@ class AdminActionsTest(TestCase): reverse("admin:admin_views_externalsubscriber_changelist"), action_data ) content = b"".join(list(response)) - self.assertEqual(content, b"This is the content of the file") + self.assertEqual( + content, b"This is the content of the file written by John Doe" + ) self.assertEqual(response.status_code, 200) def test_custom_function_action_no_perm_response(self): @@ -294,13 +297,12 @@ class AdminActionsTest(TestCase): response, """