12

以前在 Django 1.11 中,我以这种方式定义了 Django REST API:

在 url.py 中

url(r'^api/test_token$', api.test_token, name='test_token'),

在 api.py

@api_view(['POST'])
def test_token(request):
    # ----- YAML below for Swagger -----
    """
    description: test_token
    parameters:
      - name: token
        type: string
        required: true
        location: form       
    """
    token = request.POST['token']

    return Response("test_token success", status=status.HTTP_200_OK)

现在我正在迁移到 Django 3.1.5,我想知道如何以与 Django Rest Framework (DRF) 相同的方式实现上述目标。在上述特殊情况下,POST API“test_token”接受一个参数。并生成 API 文档,如 swagger/redoc(可用于测试 API)

在此处输入图像描述

一些注意事项:

如何在 Django 3.x 上实现这一点?(如标题:Django Rest Framework custom POST URL endpoints with defined parameter with Swagger or other doc)

更新:

我认为这里有某种形式的解决方案: https ://github.com/tfranzel/drf-spectacular/issues/279

由于我有很多使用 @api_view 的 API,因此对装饰器 @extend_schema 的更改文档字符串可能是最简单的迁移路径。我希望有人可以提供有关 url.py 使用 @extend_schema 进行转换的指导。这是为了实现 url 端点和招摇。谢谢。

然而,这是我与 drf-spectacular 最接近的

@extend_schema( 
 parameters=[OpenApiParameter( 
     name='token', 
     type={'type': 'string'}, 
     location=OpenApiParameter.QUERY, 
     required=False, 
     style='form', 
     explode=False, 
 )], 
 responses=OpenApiTypes.OBJECT, 
) 
@api_view(['POST'])
def test_api(request):
    # ----- YAML below for Swagger -----
    """
    description: test_api
    parameters:
      - name: token
        type: string
        required: true
        location: form       
    """
    token = request.POST['token']
    
    return Response("success test_api:" + token, status=status.HTTP_200_OK)

它给出这个(这是不正确的),注意令牌查询

curl -X POST "http://localhost:8000/api/test_token/?token=hello" -H  "accept: application/json" -H  "X-CSRFToken: JyPOSAQx04LK0aM8IUgUmkruALSNwRbeYDzUHBhCjtXafC3tnHRFsxvyg5SgMLhI" -d ""

而不是 POST 输入参数(如何得到这个?)

curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' --header 'Accept: application/json' --header 'X-CSRFToken: aExHCSwrRyStDiOhkk8Mztfth2sqonhTkUFaJbnXSFKXCynqzDQEzcRCAufYv6MC' -d 'token=hello' 'http://localhost:8000/api/test_token/

解决方案:

网址.py

from drf_yasg.utils import swagger_auto_schema 

from rest_framework.response import Response
from rest_framework import status

from rest_framework.decorators import parser_classes
from rest_framework.parsers import FormParser

token = openapi.Parameter('token', openapi.IN_FORM, type=openapi.TYPE_STRING, required=True)
something = openapi.Parameter('something', openapi.IN_FORM, type=openapi.TYPE_INTEGER, required=False)
@swagger_auto_schema(
    method="post",
    manual_parameters=[token, something],
    operation_id="token_api"
)
@api_view(['POST'])
# this is optional and insures that the view gets formdata
@parser_classes([FormParser])
def token_api(request):
    token = request.POST['token']
    something = request.POST['something']
    
    return Response("success test_api:" + token + something, status=status.HTTP_200_OK)


schema_view = get_schema_view(
   openapi.Info(
      title="Snippets API",
      default_version='v1',
      description="Test description",
      terms_of_service="https://www.google.com/policies/terms/",
      contact=openapi.Contact(email="contact@snippets.local"),
      license=openapi.License(name="BSD License"),
   ),
   public=True,
   permission_classes=[permissions.AllowAny],
)


urlpatterns = [
    
    path('token_api', token_api, name='token_api'),

    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
    
] + required_urlpatterns
4

2 回答 2

6

正如你所说,django-rest-swagger 已被弃用。

这就是为什么推荐使用drf-yasg

from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema    

class ArticleViewSet(viewsets.ModelViewSet):
    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT, 
        properties={
            'test_token': openapi.Schema(type=openapi.TYPE_STRING, description='string'),
        }
    ))
    def create(self, request, *args, **kwargs):
        ...

或者,如果您想使用 DRF 操作

    @swagger_auto_schema(method="post", request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT, 
        properties={
            'test_token': openapi.Schema(type=openapi.TYPE_STRING, description='string'),
        }
    ))
    @action(method=["post"], detail=False)
    def my_post_action(self, request, *args, **kwargs):
        ...

或者使用 api 视图:

# here we define that this view accepts a json (or object parameter) that has test_token parameter inside of it
@swagger_auto_schema(method='post', 
    request_body=openapi.Schema(
    type=openapi.TYPE_OBJECT, # object because the data is in json format
    properties={
        'test_token': openapi.Schema(type=openapi.TYPE_STRING, description='this test_token is used for...'),
    }
), operation_id="token_view")
# your view
@api_view(['POST'])
def token_view(request):
    pass

你的 url.py 看起来像这样

# define some basic info about your api for swagger
schema_view = get_schema_view(
   openapi.Info(
      title="Snippets API",
      default_version='v1',
      description="Test description",
      terms_of_service="https://www.google.com/policies/terms/",
      contact=openapi.Contact(email="contact@snippets.local"),
      license=openapi.License(name="BSD License"),
   ),
   public=True,
   permission_classes=[permissions.AllowAny],
)

urlpatterns = [
    # define your api view url
    path('token_view/', token_view),
    # define the url of the swagger ui
    url(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]
于 2021-01-29T14:11:55.933 回答
0

如果你只是想要测试 API,Django REST 框架实际上带有它自己的可浏览 API。如果你serializer_class在你的上设置一个,APIView那么它BrowsableAPIRenderer会为你找出所有相关的细节。

以下应该可以解决问题:

from rest_framework import serializers, status
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView

class MySerializer(serializers.Serializer):
    token = serializers.CharField()

class MyView(GenericAPIView):

    serializer_class = MySerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.data

        return Response("test_token success", status=status.HTTP_200_OK)
# urls.py
urlpatterns = [
    ...
    path("api/test_token", views.MyView.as_view(), name="test_token")
]

(请注意,在 Django 2+ 中,我们使用path而不是旧url模式。如果您仍想使用正则表达式模式,您可以使用path_re)。

以上假设您没有更改渲染器的默认设置。默认值为:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
}

只需浏览到相关的端点,您就会有一个很好的测试界面。

在引擎盖下,这serializer_class是设置启用此功能的事实。这与 DRF 将自动生成用于 swagger 或 redoc 之类的模式的方式相同。

于 2021-01-30T12:23:11.027 回答