Skip to content

Commit b39bde5

Browse files
committed
fix(ObtainAuthToken): Fix openapi schema generation
fix(ObtainAuthToken): Fix openapi response type fix(ObtainAuthToken): Use APIView and define get_serializer fix test
1 parent 797518a commit b39bde5

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

rest_framework/authtoken/serializers.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@
55

66

77
class AuthTokenSerializer(serializers.Serializer):
8-
username = serializers.CharField(label=_("Username"))
8+
username = serializers.CharField(
9+
label=_("Username"),
10+
write_only=True
11+
)
912
password = serializers.CharField(
1013
label=_("Password"),
1114
style={'input_type': 'password'},
12-
trim_whitespace=False
15+
trim_whitespace=False,
16+
write_only=True
17+
)
18+
token = serializers.CharField(
19+
label=_("Token"),
20+
read_only=True
1321
)
1422

1523
def validate(self, attrs):

rest_framework/authtoken/views.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from rest_framework.compat import coreapi, coreschema
55
from rest_framework.response import Response
66
from rest_framework.schemas import ManualSchema
7+
from rest_framework.schemas import coreapi as coreapi_schema
78
from rest_framework.views import APIView
89

910

@@ -13,7 +14,8 @@ class ObtainAuthToken(APIView):
1314
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
1415
renderer_classes = (renderers.JSONRenderer,)
1516
serializer_class = AuthTokenSerializer
16-
if coreapi is not None and coreschema is not None:
17+
18+
if coreapi_schema.is_enabled():
1719
schema = ManualSchema(
1820
fields=[
1921
coreapi.Field(
@@ -38,9 +40,19 @@ class ObtainAuthToken(APIView):
3840
encoding="application/json",
3941
)
4042

43+
def get_serializer_context(self):
44+
return {
45+
'request': self.request,
46+
'format': self.format_kwarg,
47+
'view': self
48+
}
49+
50+
def get_serializer(self, *args, **kwargs):
51+
kwargs['context'] = self.get_serializer_context()
52+
return self.serializer_class(*args, **kwargs)
53+
4154
def post(self, request, *args, **kwargs):
42-
serializer = self.serializer_class(data=request.data,
43-
context={'request': request})
55+
serializer = self.get_serializer(data=request.data)
4456
serializer.is_valid(raise_exception=True)
4557
user = serializer.validated_data['user']
4658
token, created = Token.objects.get_or_create(user=user)

tests/schemas/test_openapi.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.utils.translation import gettext_lazy as _
88

99
from rest_framework import filters, generics, pagination, routers, serializers
10+
from rest_framework.authtoken.views import obtain_auth_token
1011
from rest_framework.compat import uritemplate
1112
from rest_framework.parsers import JSONParser, MultiPartParser
1213
from rest_framework.renderers import JSONRenderer, OpenAPIRenderer
@@ -819,6 +820,7 @@ class ExampleStringTagsViewSet(views.ExampleGenericViewSet):
819820

820821
def test_auto_generated_apiview_tags(self):
821822
class RestaurantAPIView(views.ExampleGenericAPIView):
823+
schema = AutoSchema(operation_id_base="restaurant")
822824
pass
823825

824826
class BranchAPIView(views.ExampleGenericAPIView):
@@ -932,3 +934,35 @@ def test_schema_information_empty(self):
932934

933935
assert schema['info']['title'] == ''
934936
assert schema['info']['version'] == ''
937+
938+
def test_authtoken_serializer(self):
939+
patterns = [
940+
url(r'^api-token-auth/', obtain_auth_token)
941+
]
942+
generator = SchemaGenerator(patterns=patterns)
943+
944+
request = create_request('/')
945+
schema = generator.get_schema(request=request)
946+
947+
print(schema)
948+
949+
route = schema['paths']['/api-token-auth/']['post']
950+
951+
body_schema = route['requestBody']['content']['application/json']['schema']
952+
assert body_schema == {
953+
'type': 'object',
954+
'properties': {
955+
'username': {'type': 'string', 'writeOnly': True},
956+
'password': {'type': 'string', 'writeOnly': True},
957+
},
958+
'required': ['username', 'password']
959+
}
960+
961+
response_schema = route['responses']['201']['content']['application/json']['schema']
962+
assert response_schema == {
963+
'type': 'object',
964+
'properties': {
965+
'token': {'type': 'string', 'readOnly': True},
966+
},
967+
'required': []
968+
}

0 commit comments

Comments
 (0)