在将 APIView 与 django-rest-swagger 一起使用时,如何为 POST 请求指定参数
How can I specify the parameter for POST requests while using APIView with django-rest-swagger
在 Django REST Swagger (2.1.0) 的最新版本中,YAML 文档字符串已被弃用。我无法大摇大摆地显示 POST 请求参数。
这是我的看法
class UserAuthenticationView(APIView):
def post(self, request, *args, **kwargs):
serializer = UserAuthenticationSerializer(data=self.request.data)
if serializer.is_valid():
user = serializer.validated_data['user']
return Response({'token': user.auth_token.key}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED)
这是我的序列化器
class UserAuthenticationSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
def validate(self, attrs):
username = attrs.get('username')
password = attrs.get('password')
if username and password:
user = authenticate(username=username, password=password)
if user:
if not user.is_active:
msg = 'User account is disabled.'
raise serializers.ValidationError(msg, code='authorization')
else:
msg = 'Unable to log in with provided credentials.'
raise serializers.ValidationError(msg, code='authorization')
else:
msg = 'Must include "username" and "password".'
raise serializers.ValidationError(msg, code='authorization')
attrs['user'] = user
return attrs
这是我在生成的
中得到的
我没有收到包含 POST 数据字段的表单。我如何获得它?
这是其余框架获取架构代码(部分):
def get_serializer_fields(self, path, method, view):
"""
Return a list of `coreapi.Field` instances corresponding to any
request body input, as determined by the serializer class.
"""
if method not in ('PUT', 'PATCH', 'POST'):
return []
if not hasattr(view, 'get_serializer'):
return []
serializer = view.get_serializer()
if isinstance(serializer, serializers.ListSerializer):
return [
coreapi.Field(
name='data',
location='body',
required=True,
type='array'
)
]
...
如您所见 - 如果您在视图中定义 get_serializer
方法,它应该可以工作 - returns UserAuthenticationSerializer
.
-- 编辑--
忘记:快乐编码。
django-rest-swagger 使用 rest_framework.schemas.SchemaGenerator 生成模式和 SchemaGenerator 使用 get_serializer_fields 获取视图的序列化器信息。 get_serializer_fields 检查视图是否有 get_serializer 方法来生成表单。 GenericAPIView 提供了 get_serializer 所以从它继承就足够了。
从 GenericAPIView
继承视图而不是简单的 APIView
。并使用适当的序列化程序
添加 serializer_class
属性
from rest_framework.generics import GenericAPIView
class UserAuthenticationView(GenericAPIView):
serializer_class = UserAuthenticationSerializer
def post(self, request, *args, **kwargs):
serializer = UserAuthenticationSerializer(data=self.request.data)
if serializer.is_valid():
user = serializer.validated_data['user']
return Response({'token': user.auth_token.key}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED)
自定义 ViewSet 的工作示例,django-rest-swagger==2.2.0:
from rest_framework import viewsets
from rest_framework.schemas import AutoSchema
from rest_framework.compat import coreapi, coreschema
from rest_framework.decorators import action
class DeviceViewSchema(AutoSchema):
"""
Schema customizations for DeviceViewSet
"""
def get_manual_fields(self, path, method):
extra_fields = []
if path.endswith('/send_command/'):
extra_fields = [
coreapi.Field(
"command",
required=True,
location="form",
schema=coreschema.String()
),
coreapi.Field(
"params",
required=False,
location="form",
schema=coreschema.String()
),
]
manual_fields = super().get_manual_fields(path, method)
return manual_fields + extra_fields
class DeviceViewSet(viewsets.ViewSet):
lookup_field = 'channel'
lookup_value_regex = '[\w-]+'
schema = DeviceViewSchema()
@action(methods=['post'], detail=True, url_name='send_command')
def send_command(self, request, channel):
"""
Send command to device
Parameters:
- command: string
- params: string (JSON encoded list or dict)
"""
...
最后的结果是:
在 Django REST Swagger (2.1.0) 的最新版本中,YAML 文档字符串已被弃用。我无法大摇大摆地显示 POST 请求参数。
这是我的看法
class UserAuthenticationView(APIView):
def post(self, request, *args, **kwargs):
serializer = UserAuthenticationSerializer(data=self.request.data)
if serializer.is_valid():
user = serializer.validated_data['user']
return Response({'token': user.auth_token.key}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED)
这是我的序列化器
class UserAuthenticationSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
def validate(self, attrs):
username = attrs.get('username')
password = attrs.get('password')
if username and password:
user = authenticate(username=username, password=password)
if user:
if not user.is_active:
msg = 'User account is disabled.'
raise serializers.ValidationError(msg, code='authorization')
else:
msg = 'Unable to log in with provided credentials.'
raise serializers.ValidationError(msg, code='authorization')
else:
msg = 'Must include "username" and "password".'
raise serializers.ValidationError(msg, code='authorization')
attrs['user'] = user
return attrs
这是我在生成的
我没有收到包含 POST 数据字段的表单。我如何获得它?
这是其余框架获取架构代码(部分):
def get_serializer_fields(self, path, method, view):
"""
Return a list of `coreapi.Field` instances corresponding to any
request body input, as determined by the serializer class.
"""
if method not in ('PUT', 'PATCH', 'POST'):
return []
if not hasattr(view, 'get_serializer'):
return []
serializer = view.get_serializer()
if isinstance(serializer, serializers.ListSerializer):
return [
coreapi.Field(
name='data',
location='body',
required=True,
type='array'
)
]
...
如您所见 - 如果您在视图中定义 get_serializer
方法,它应该可以工作 - returns UserAuthenticationSerializer
.
-- 编辑--
忘记:快乐编码。
django-rest-swagger 使用 rest_framework.schemas.SchemaGenerator 生成模式和 SchemaGenerator 使用 get_serializer_fields 获取视图的序列化器信息。 get_serializer_fields 检查视图是否有 get_serializer 方法来生成表单。 GenericAPIView 提供了 get_serializer 所以从它继承就足够了。
从 GenericAPIView
继承视图而不是简单的 APIView
。并使用适当的序列化程序
serializer_class
属性
from rest_framework.generics import GenericAPIView
class UserAuthenticationView(GenericAPIView):
serializer_class = UserAuthenticationSerializer
def post(self, request, *args, **kwargs):
serializer = UserAuthenticationSerializer(data=self.request.data)
if serializer.is_valid():
user = serializer.validated_data['user']
return Response({'token': user.auth_token.key}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED)
自定义 ViewSet 的工作示例,django-rest-swagger==2.2.0:
from rest_framework import viewsets
from rest_framework.schemas import AutoSchema
from rest_framework.compat import coreapi, coreschema
from rest_framework.decorators import action
class DeviceViewSchema(AutoSchema):
"""
Schema customizations for DeviceViewSet
"""
def get_manual_fields(self, path, method):
extra_fields = []
if path.endswith('/send_command/'):
extra_fields = [
coreapi.Field(
"command",
required=True,
location="form",
schema=coreschema.String()
),
coreapi.Field(
"params",
required=False,
location="form",
schema=coreschema.String()
),
]
manual_fields = super().get_manual_fields(path, method)
return manual_fields + extra_fields
class DeviceViewSet(viewsets.ViewSet):
lookup_field = 'channel'
lookup_value_regex = '[\w-]+'
schema = DeviceViewSchema()
@action(methods=['post'], detail=True, url_name='send_command')
def send_command(self, request, channel):
"""
Send command to device
Parameters:
- command: string
- params: string (JSON encoded list or dict)
"""
...
最后的结果是: