Prevent head method mapping to coerce action name (#7729)

This commit is contained in:
Jonas Lundberg 2022-08-12 13:00:55 +02:00 committed by GitHub
parent 791d48c690
commit df584350b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 1 deletions

View File

@ -198,7 +198,11 @@ class SchemaGenerator(BaseSchemaGenerator):
if is_custom_action(action): if is_custom_action(action):
# Custom action, eg "/users/{pk}/activate/", "/users/active/" # Custom action, eg "/users/{pk}/activate/", "/users/active/"
if len(view.action_map) > 1: mapped_methods = {
# Don't count head mapping, e.g. not part of the schema
method for method in view.action_map if method != 'head'
}
if len(mapped_methods) > 1:
action = self.default_mapping[method.lower()] action = self.default_mapping[method.lower()]
if action in self.coerce_method_names: if action in self.coerce_method_names:
action = self.coerce_method_names[action] action = self.coerce_method_names[action]

View File

@ -754,6 +754,67 @@ class TestSchemaGeneratorWithManyToMany(TestCase):
assert schema == expected assert schema == expected
@unittest.skipUnless(coreapi, 'coreapi is not installed')
@override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema'})
class TestSchemaGeneratorActionKeysViewSets(TestCase):
def test_action_not_coerced_for_get_and_head(self):
"""
Ensure that action name is preserved when action map contains "head".
"""
class CustomViewSet(GenericViewSet):
serializer_class = EmptySerializer
@action(methods=['get', 'head'], detail=True)
def custom_read(self, request, pk):
raise NotImplementedError
@action(methods=['put', 'patch'], detail=True)
def custom_mixed_update(self, request, pk):
raise NotImplementedError
self.router = DefaultRouter()
self.router.register('example', CustomViewSet, basename='example')
self.patterns = [
path('', include(self.router.urls))
]
generator = SchemaGenerator(title='Example API', patterns=self.patterns)
schema = generator.get_schema()
expected = coreapi.Document(
url='',
title='Example API',
content={
'example': {
'custom_read': coreapi.Link(
url='/example/{id}/custom_read/',
action='get',
fields=[
coreapi.Field('id', required=True, location='path', schema=coreschema.String()),
]
),
'custom_mixed_update': {
'update': coreapi.Link(
url='/example/{id}/custom_mixed_update/',
action='put',
fields=[
coreapi.Field('id', required=True, location='path', schema=coreschema.String()),
]
),
'partial_update': coreapi.Link(
url='/example/{id}/custom_mixed_update/',
action='patch',
fields=[
coreapi.Field('id', required=True, location='path', schema=coreschema.String()),
]
)
}
}
}
)
assert schema == expected
@unittest.skipUnless(coreapi, 'coreapi is not installed') @unittest.skipUnless(coreapi, 'coreapi is not installed')
@override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema'}) @override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema'})
class Test4605Regression(TestCase): class Test4605Regression(TestCase):