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.
ViewSet Class | Tags
----------------|------------
User | User
UserView | User
UserViewSet | user
Examples:
2. If View is not an instance of ViewSet, tag name will be first element from the path. Consider below examples.
ViewSet Class | Tags
----------------|------------
User | ['user']
UserView | ['user']
UserViewSet | ['user']
PascalCaseXYZ | ['pascal case xyz']
IPAddressView | ['ip address']
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'] == []