Fix viewset actions dict being mutated after first request (#9747)

This commit is contained in:
mag123c 2025-12-18 22:34:47 +09:00
parent 055c422b34
commit 6eaf6bbfa5
2 changed files with 18 additions and 4 deletions

View File

@ -103,17 +103,18 @@ class ViewSetMixin:
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if 'get' in actions and 'head' not in actions:
actions['head'] = actions['get']
bound_actions = dict(actions)
if 'get' in bound_actions and 'head' not in bound_actions:
bound_actions['head'] = bound_actions['get']
# We also store the mapping of request methods to actions,
# so that we can later set the action attribute.
# eg. `self.action = 'list'` on an incoming GET request.
self.action_map = actions
self.action_map = bound_actions
# Bind methods to actions
# This is the bit that's different to a standard view
for method, action in actions.items():
for method, action in bound_actions.items():
handler = getattr(self, action)
setattr(self, method, handler)

View File

@ -190,6 +190,19 @@ class InitializeViewSetsTestCase(TestCase):
assert get.view.action == 'list'
assert head.view.action == 'list'
def test_actions_dict_not_mutated(self):
"""
The original actions dict passed to as_view() should not be mutated.
Regression test for #9747.
"""
actions = {'get': 'list'}
view = ActionViewSet.as_view(actions=actions)
assert 'head' not in actions
view(factory.get('/'))
assert 'head' not in actions
assert view.actions == {'get': 'list'}
def test_viewset_action_attr_for_extra_action(self):
view = ActionViewSet.as_view(actions=dict(ActionViewSet.list_action.mapping))