Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions rest_framework/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,18 @@ def as_view(cls, actions=None, **initkwargs):
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)

Expand Down
13 changes: 13 additions & 0 deletions tests/test_viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,19 @@ def test_viewset_action_attr(self):
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))

Expand Down
Loading