fix changes given by kevin-brown

This commit is contained in:
Dhaval Mehta 2020-02-13 00:09:19 +05:30
parent 9c3a632e29
commit b0f11cdd29
3 changed files with 42 additions and 24 deletions

View File

@ -222,23 +222,30 @@ Tags can be used for logical grouping operations. Each tag name in the list MUST
---
**Django REST Framework generates tags automatically with following logic:**
1. Extract tag name from `ViewSet`. If `ViewSet` name ends with `ViewSet`, or `View`, it will be truncated from tag name.
1. Extract tag from `ViewSet`.
1. If `ViewSet` name ends with `ViewSet`, or `View`, remove them.
2. Convert class name into words & join each word with a space.
Examples:
ViewSet Class | Tags
----------------|------------
User | ['user']
UserView | ['user']
UserViewSet | ['user']
PascalCaseXYZ | ['pascal case xyz']
IPAddressView | ['ip address']
ViewSet Class | Tags
----------------|------------
User | User
UserView | User
UserViewSet | user
2. If View is not an instance of ViewSet, tag name will be first element from the path. Consider below examples.
2. If View is not an instance of ViewSet, tag name will be first element from the path. Also, any `-` or `_` in path name will be converted as a space.
Consider below examples.
Example 1: Consider a user management system. The following table will illustrate the tag generation logic.
Here first element from the paths is: `users`. Hence tag wil be `users`
Http Method | Path | Tags
-------------------------------------|-------------------|-------------
PUT, PATCH, GET(Retrieve), DELETE | /users/{id}/ | [users]
POST, GET(List) | /users/ | [users]
PUT, PATCH, GET(Retrieve), DELETE | /users/{id}/ | ['users']
POST, GET(List) | /users/ | ['users']
Example 2: Consider a restaurant management system. The System has restaurants. Each restaurant has branches.
Consider REST APIs to deal with a branch of a particular restaurant.
@ -246,11 +253,21 @@ Tags can be used for logical grouping operations. Each tag name in the list MUST
Http Method | Path | Tags
-------------------------------------|----------------------------------------------------|-------------------
PUT, PATCH, GET(Retrieve), DELETE: | /restaurants/{restaurant_id}/branches/{branch_id} | [restaurants]
POST, GET(List): | /restaurants/{restaurant_id}/branches/ | [restaurants]
PUT, PATCH, GET(Retrieve), DELETE: | /restaurants/{restaurant_id}/branches/{branch_id} | ['restaurants']
POST, GET(List): | /restaurants/{restaurant_id}/branches/ | ['restaurants']
Example 3: Consider Order items for an e commerce company.
Http Method | Path | Tags
-------------------------------------|-------------------------|-------------
PUT, PATCH, GET(Retrieve), DELETE | /order-items/{id}/ | ['order items']
POST, GET(List) | /order-items/ | ['order items']
---
**You can override auto-generated tags by passing a list of tags to each `View` by passing `tags` as an argument to the constructor of `AutoSchema`. `tags` argument can be:**
**You can override auto-generated tags by passing `tags` argument to the constructor of `AutoSchema`.**
**`tags` argument can be a**
1. list of string.
```python
class MyView(APIView):

View File

@ -15,6 +15,7 @@ from rest_framework import exceptions, renderers, serializers
from rest_framework.compat import uritemplate
from rest_framework.fields import _UnvalidatedField, empty
from ..utils.formatting import camelcase_to_spaces
from .generators import BaseSchemaGenerator
from .inspectors import ViewInspector
from .utils import get_pk_description, is_list_view
@ -597,7 +598,7 @@ class AutoSchema(ViewInspector):
name = name[:-7]
elif name.endswith('View'):
name = name[:-4]
return [name]
return [camelcase_to_spaces(name).lower()]
# First element of a specific path could be valid tag. This is a fallback solution.
# PUT, PATCH, GET(Retrieve), DELETE: /users/{id}/ tags = [users]
@ -605,4 +606,4 @@ class AutoSchema(ViewInspector):
if path.startswith('/'):
path = path[1:]
return [path.split('/')[0]]
return [path.split('/')[0].translate(str.maketrans({'-': ' ', '_': ' '}))]

View File

@ -776,25 +776,25 @@ class TestOperationIntrospection(TestCase):
]
def test_auto_generated_viewset_tags(self):
class ExampleViewSet(views.ExampleTagsViewSet):
class ExampleIPViewSet(views.ExampleTagsViewSet):
pass
class ExampleView(views.ExampleTagsViewSet):
class ExampleXYZView(views.ExampleTagsViewSet):
pass
class Example(views.ExampleTagsViewSet):
pass
router = routers.SimpleRouter()
router.register('test1', ExampleViewSet, basename="test")
router.register('test2', ExampleView, basename="test")
router.register('test1', ExampleIPViewSet, basename="test")
router.register('test2', ExampleXYZView, basename="test")
router.register('test3', Example, basename="test")
generator = SchemaGenerator(patterns=router.urls)
schema = generator.get_schema(request=create_request('/'))
assert schema['paths']['/test1/{id}/']['get']['tags'] == ['Example']
assert schema['paths']['/test2/{id}/']['get']['tags'] == ['Example']
assert schema['paths']['/test3/{id}/']['get']['tags'] == ['Example']
assert schema['paths']['/test1/{id}/']['get']['tags'] == ['example ip']
assert schema['paths']['/test2/{id}/']['get']['tags'] == ['example xyz']
assert schema['paths']['/test3/{id}/']['get']['tags'] == ['example']
assert schema['tags'] == []
def test_auto_generated_apiview_tags(self):
@ -805,12 +805,12 @@ class TestOperationIntrospection(TestCase):
pass
url_patterns = [
url(r'^restaurants/?$', RestaurantAPIView.as_view()),
url(r'^any-dash_underscore/?$', RestaurantAPIView.as_view()),
url(r'^restaurants/branches/?$', BranchAPIView.as_view())
]
generator = SchemaGenerator(patterns=url_patterns)
schema = generator.get_schema(request=create_request('/'))
assert schema['paths']['/restaurants/']['get']['tags'] == ['restaurants']
assert schema['paths']['/any-dash_underscore/']['get']['tags'] == ['any dash underscore']
assert schema['paths']['/restaurants/branches/']['get']['tags'] == ['restaurants']
assert schema['tags'] == []