【问题标题】:django-rest-swagger: How can I specify the parameter type in the docstringdjango-rest-swagger:如何在文档字符串中指定参数类型
【发布时间】:2014-11-09 19:47:33
【问题描述】:

我正在使用 django-rest-framwork 和 django-rest-swagger。

问题是我直接从请求正文中获取数据:

def put(self, request, format=None):
    """                                                                                                                                                                                                
    This text is the description for this API                                                                                                                                                          
    username -- username                                                                                                                                                                               
    password -- password                                                                                                                                                                               
    """
    username = request.DATA['username']
    password = request.DATA['password']

但是当我尝试来自 swagger-ui 的请求时,我无法指定“参数类型”(默认情况下它是查询,无法从文档字符串中找到更改它的方法)

我已经设法通过从文件 "introspectors.py" 更改函数 build_query_params_from_docstring 中的某些行来解决我的问题,但我想知道是否还有其他方法去做吧。

【问题讨论】:

    标签: python django-rest-framework


    【解决方案1】:

    更新:此答案仅适用于 django-rest-swagger

    文档:http://django-rest-swagger.readthedocs.org/en/latest/yaml.html

    如果要放置表单数据:

    def put(self, request, format=None):
        """
        This text is the description for this API.
    
        ---
        parameters:
        - name: username
          description: Foobar long description goes here
          required: true
          type: string
          paramType: form
        - name: password
          paramType: form
          required: true
          type: string
        """
        username = request.DATA['username']
        password = request.DATA['password']
    

    对于 JSON 正文,您可以执行以下操作:

    def put(...):
        """
        ...
    
        ---
        parameters:
        - name: body
          description: JSON object containing two strings: password and username.
          required: true
          paramType: body
          pytype: RequestSerializer
        """
        ...
    

    【讨论】:

    【解决方案2】:

    在您的视图集中定义一个过滤器类。 django-rest 不再为参数做这个 yaml 东西了。您在过滤器类中定义的字段将在您的 openapi / swagger 文档中显示为字段。这很整洁。

    阅读完整文档。

    http://www.django-rest-framework.org/apiguide/filtering/#djangofilterbackend

    from django_filters.rest_framework.filterset import FilterSet
    
    class ProductFilter(FilterSet):
    
        class Meta(object):
            models = models.Product
            fields = (
                'name', 'category', 'id', )
    
    
    class PurchasedProductsList(generics.ListAPIView):
        """
        Return a list of all the products that the authenticated
        user has ever purchased, with optional filtering.
        """
        model = Product
        serializer_class = ProductSerializer
        filter_class = ProductFilter
    
        def get_queryset(self):
            user = self.request.user
            return user.purchase_set.all()
    

    filterseet 中定义的字段将显示在 de 文档中。 但不会有描述。

    【讨论】:

    • 这是正确答案。这就是你应该从 Rest Swagger v2.0 及更高版本实现它的方式。
    • @api_view 怎么样?
    • 这个答案可以用一些示例代码来扩展吗?
    • django rest 框架的链接断开
    【解决方案3】:

    类似于 John VanBuskirk 的回答,这就是我所拥有的:

    实际手动创建的文档:

    drf_api/business/schema.py

    # encoding: utf-8
    from __future__ import unicode_literals
    from __future__ import absolute_import
    import coreapi
    
    schema = coreapi.Document(
        title='Business Search API',
        url='/api/v3/business/',
        content={
            'search': coreapi.Link(
                url='/',
                action='get',
                fields=[
                    coreapi.Field(
                        name='what',
                        required=True,
                        location='query',
                        description='Search term'
                    ),
                    coreapi.Field(
                        name='where',
                        required=True,
                        location='query',
                        description='Search location'
                    ),
                ],
                description='Search business listings'
            )
        }
    )
    

    然后复制get_swagger_view函数并自定义:

    drf_api/swagger.py

    # encoding: utf-8
    from __future__ import unicode_literals
    from __future__ import absolute_import
    from rest_framework import exceptions
    from rest_framework.permissions import AllowAny
    from rest_framework.renderers import CoreJSONRenderer
    from rest_framework.response import Response
    from rest_framework.views import APIView
    from rest_framework_swagger import renderers
    from django.utils.module_loading import import_string
    
    
    def get_swagger_view(schema_location):
        """
        Returns schema view which renders Swagger/OpenAPI.
        """
        class SwaggerSchemaView(APIView):
            _ignore_model_permissions = True
            exclude_from_schema = True
            permission_classes = [AllowAny]
            renderer_classes = [
                CoreJSONRenderer,
                renderers.OpenAPIRenderer,
                renderers.SwaggerUIRenderer
            ]
    
            def get(self, request):
                schema = None
    
                try:
                    schema = import_string(schema_location)
                except:
                    pass
    
                if not schema:
                    raise exceptions.ValidationError(
                        'The schema generator did not return a schema Document'
                    )
    
                return Response(schema)
    
    
        return SwaggerSchemaView.as_view()
    

    然后将其连接到 urls.py

    from ..swagger import get_swagger_view
    from . import views
    
    schema_view = get_swagger_view(schema_location='drf_api.business.schema.schema')
    
    urlpatterns = [
        url(r'^swagger/$', schema_view),
    

    【讨论】:

    • 如果我们使用自定义 schema_view,我们将如何添加 location='body' 以及我们将如何展示 body 示例?
    【解决方案4】:

    我在定义参数类型方面取得成功的唯一方法是创建一个视图来定义我想要的内容,而无需使用生成器。

    class SwaggerSchemaView(APIView):
    permission_classes = [IsAuthenticatedOrReadOnly,]
    renderer_classes = [renderers.OpenAPIRenderer, renderers.SwaggerUIRenderer]
    
    schema = coreapi.Document(
        title='Thingy API thing',
            'range': coreapi.Link(
                url='/range/{start}/{end}',
                action='get',
                fields=[
                    coreapi.Field(
                        name='start',
                        required=True,
                        location='path',
                        description='start time as an epoch',
                        type='integer'
                    ),
                    coreapi.Field(
                        name='end',
                        required=True,
                        location='path',
                        description='end time as an epoch',
                        type='integer'
                    )
                ],
                description='show the things between the things'
            ),
        }
    )
    

    然后在 urls.py 中使用该类

    urlpatterns = [
        url(r'^$', SwaggerSchemaView.as_view()),
        ...
    ]
    

    【讨论】:

      【解决方案5】:

      对于最新的 django-rest-framework > 3.7django-rest-swagger > 2 ,请通过以下链接找到有效的解决方案

      https://github.com/marcgibbons/django-rest-swagger/issues/549#issuecomment-371860030

      【讨论】:

        【解决方案6】:

        对于 Django Rest Framework >= 2.0

        我正在使用序列化程序并通过装饰器应用于视图函数:

        from types import MethodType
        from typing import Optional, List, Callable, Any
        
        from rest_framework.decorators import api_view as drf_api_view
        from rest_framework.serializers import BaseSerializer
        
        Function = Callable[..., Any]
        
        
        def api_view(
            http_method_names: Optional[List[str]] = None,
            use_serializer: Optional[BaseSerializer] = None
        ) -> Function:
            if use_serializer is None:
                return drf_api_view(http_method_names)
        
            def api_view_deco_wrap(view: Function) -> Function:
                nonlocal http_method_names, use_serializer
        
                decorated_view = drf_api_view(http_method_names)(view)
        
                if use_serializer:
                    decorated_view.cls.get_serializer = \
                        MethodType(lambda s: use_serializer(), decorated_view.cls)
        
                return decorated_view
        
            return api_view_deco_wrap
        

        然后在我使用的函数中:

        @util.api_view(["POST"], use_serializer=serializers.MySerializer)
        def replace(request, pk):
            pass
        

        并且有效!!!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-10
          • 2016-05-04
          • 2018-06-14
          • 1970-01-01
          • 1970-01-01
          • 2017-01-09
          相关资源
          最近更新 更多