drf-yasg 之@swagger_auto_schema装饰器的用法

自定义模式生成

如果默认规范生成与您希望实现的不完全匹配drf-yasg,则默认提供一些自定义行为挂钩。

排除端点

可以您通过将其类级swagger_schema 属性设置为阻止视图所有游戏在扬鞭视图None,可以或者通过auto_schema@swagger_auto_schema中将覆盖设置为无  来阻止包含操作

class UserList(APIView):
   swagger_schema = None

   # all methods of the UserList class will be excluded
   ...

# only the GET method will be shown in Swagger
@swagger_auto_schema(method='put', auto_schema=None)
@swagger_auto_schema(methods=['get'], ...)
@api_view(['GET', 'PUT'])
def user_detail(request, pk):
   pass

@swagger_auto_schema装饰

可以您在视图函数上使用装饰器来覆盖生成的某些属性例如,在一中@swagger_auto_schemaOperationViewSet

@swagger_auto_schema(operation_description="partial_update description override", responses={404: 'slug not found'})
def partial_update(self, request, *args, **kwargs):
   """partial_update method docstring"""
   ...

覆盖将操作的描述,并记录没有正文和给定描述的404响应。PATCH /article/{id}/

可以您在哪里‧使用装饰器取决于您的视图类型:@swagger_auto_schema

  • 对于基于函数的@api_viewS,因为相同的视图可以处理多个方法,因此代表多个操作,如果要覆盖不同的操作,则必须多次添加装饰器:

    test_param = openapi.Parameter('test', openapi.IN_QUERY, description="test manual param", type=openapi.TYPE_BOOLEAN)
    user_response = openapi.Response('response description', UserSerializer)
    
    # 'method' can be used to customize a single HTTP method of a view
    @swagger_auto_schema(method='get', manual_parameters=[test_param], responses={200: user_response})
    # 'methods' can be used to apply the same modification to multiple methods
    @swagger_auto_schema(methods=['put', 'post'], request_body=UserSerializer)
    @api_view(['GET', 'PUT', 'POST'])
    def user_detail(request, pk):
        ...
    
  • 对于基于类APIViewGenericAPIView状语从句:非ViewSet衍生物,你必须装饰每个操作的相应方法:

    class UserList(APIView):
       @swagger_auto_schema(responses={200: UserSerializer(many=True)})
       def get(self, request):
          ...
    
       @swagger_auto_schema(operation_description="description")
       def post(self, request):
          ...
    
  • ViewSet, ,GenericViewSetModelViewSet每个因为集视图对应于多个路径,必须则装饰作用英文的方法,即listcreateretrieve等。
    此外,@actionS,@ list_route` 秒或@detail_route在视图集定义,例如基于函数API视图S,可以响应多个HTTP方法因此具有必须单独修饰的多个操作

    class ArticleViewSet(viewsets.ModelViewSet):
       # method or 'methods' can be skipped because the list_route only handles a single method (GET)
       @swagger_auto_schema(operation_description='GET /articles/today/')
       @action(detail=False, methods=['get'])
       def today(self, request):
          ...
    
       @swagger_auto_schema(method='get', operation_description="GET /articles/{id}/image/")
       @swagger_auto_schema(method='post', operation_description="POST /articles/{id}/image/")
       @action(detail=True, methods=['get', 'post'], parser_classes=(MultiPartParser,))
       def image(self, request, id=None):
          ...
    
       @swagger_auto_schema(operation_description="PUT /articles/{id}/")
       def update(self, request, *args, **kwargs):
          ...
    
       @swagger_auto_schema(operation_description="PATCH /articles/{id}/")
       def partial_update(self, request, *args, **kwargs):
          ...
    

小费

如果你想自定义你自己没有实现的方法的生成,你可以  swagger_auto_schema结合使用Django  method_decorator

@method_decorator(name='list', decorator=swagger_auto_schema(
    operation_description="description from swagger_auto_schema via method_decorator"
))
class ArticleViewSet(viewsets.ModelViewSet):
   ...

这样可以避免不必要地覆盖该方法。

小费

您可以更进一步直接装饰结果as_view,与方法覆盖@api_view如上所述相同:

decorated_login_view = \
   swagger_auto_schema(
      method='post',
      responses={status.HTTP_200_OK: LoginResponseSerializer}
   )(LoginView.as_view())

urlpatterns = [
   ...
   url(r'^login/$', decorated_login_view, name='login')
]

可以这让您避免完全跳过不必要的子类

警告

但是,请注意上述两种方法都可以通过替换基类本身上的/装饰方法来产生意外(也许是令人惊讶的)结果。

串行  Meta嵌套类

可以您通过向序列化程序添加Meta类来定义一些每序列化程序选项对话,例如:

class WhateverSerializer(Serializer):
   ...

   class Meta:
      ... options here ...

可用选项包括:

  • ref_name - 一个字符串,将用作此序列化程序类的模型定义名称;  将其设置为  None将强制序列化程序在所使用的任何位置生成为内联模型。如果两个序列化程序具有相同的ref_name,则它们的用法将被替换为对相同定义的引用。如果未指定此选项,则所有序列化程序都具有从其类名派生的隐式名称,减去任何 Serializer后缀(例如UserSerializer- >  UserSerializerWithSuffix- >  SerializerWithSuffix
  • swagger_schema_fields- 将字段名称映射到值的字典这些属性将在从中生成对象上设置字段名称必须是python值,根据它们转换为Swagger 属性名称属性名称和值必须符合 OpenAPI 2.0规范SchemaSchemaSerializerSchemamake_swagger_name()

子类化和扩展

SwaggerAutoSchema

对于更高级的控制,您可以进行子类化- 请参阅文档页面以获取可以覆盖的方法列表。SwaggerAutoSchema

您可以通过使用上述@swagger_auto_schema 装饰器在视图方法上设置自定义子类,其将设置为swagger_schema视图类上指定的类级属性,或 通过设置全局设置子类来使用 

例如,要生成所有操作ID为camel case,您可以执行以下操作:

from inflection import camelize

class CamelCaseOperationIDAutoSchema(SwaggerAutoSchema):
   def get_operation_id(self, operation_keys):
      operation_id = super(CamelCaseOperationIDAutoSchema, self).get_operation_id(operation_keys)
      return camelize(operation_id, uppercase_first_letter=False)


SWAGGER_SETTINGS = {
   'DEFAULT_AUTO_SCHEMA_CLASS': 'path.to.CamelCaseOperationIDAutoSchema',
   ...
}

OpenAPISchemaGenerator

如果您需要控制比对象更高级别的东西(例如整体文档结构,元数据中的供应商扩展),您也可以再次进行子类化- 请参阅文档页面以获取其方法列表。OperationOpenAPISchemaGenerator

自这个定义生成器可以通过把它设置为使用一个的使用generator_classSchemaViewget_schema_view()

Inspector

对于定制相关的特定领域,串行器,过滤器或分页程序类行为可以实施,  班并与使用它们@swagger_auto_schema 或一个  相关的设置FieldInspectorSerializerInspectorFilterInspectorPaginatorInspector

像可以实现这样为所有参数添加描述的一个  FilterInspectorDjangoFilterBackend

class DjangoFilterDescriptionInspector(CoreAPICompatInspector):
   def get_filter_parameters(self, filter_backend):
      if isinstance(filter_backend, DjangoFilterBackend):
         result = super(DjangoFilterDescriptionInspector, self).get_filter_parameters(filter_backend)
         for param in result:
            if not param.get('description', ''):
               param.description = "Filter the returned list by {field_name}".format(field_name=param.name)

         return result

      return NotHandled

@method_decorator(name='list', decorator=swagger_auto_schema(
   filter_inspectors=[DjangoFilterDescriptionInspector]
))
class ArticleViewSet(viewsets.ModelViewSet):
   filter_backends = (DjangoFilterBackend,)
   filter_fields = ('title',)
   ...

第二个例子,从所有生成的对象中删除属性  FieldInspectortitleSchema

class NoSchemaTitleInspector(FieldInspector):
   def process_result(self, result, method_name, obj, **kwargs):
      # remove the `title` attribute of all Schema objects
      if isinstance(result, openapi.Schema.OR_REF):
         # traverse any references and alter the Schema object in place
         schema = openapi.resolve_ref(result, self.components)
         schema.pop('title', None)

         # no ``return schema`` here, because it would mean we always generate
         # an inline `object` instead of a definition reference

      # return back the same object that we got - i.e. a reference if we got a reference
      return result


class NoTitleAutoSchema(SwaggerAutoSchema):
   field_inspectors = [NoSchemaTitleInspector] + swagger_settings.DEFAULT_FIELD_INSPECTORS

class ArticleViewSet(viewsets.ModelViewSet):
   swagger_schema = NoTitleAutoSchema
   ...

注意

关于引用的注释 -  对象有时通过引用(输出实际上,这就是在OpenAPI中实现命名模型的方式:SchemaSchemaRef

  • 在输出文件中,一个有definitions所有游戏所有模型对象部分Schema
  • 模型的每个用法都引用该单个对象 - 例如,在上面的ArticleViewSet中,包含模型的所有请求和响应都将引用相同的模式定义。SchemaArticle'$ref': '#/definitions/Article'

的英文这仅为通过遇到的每个序列化程序生成一个 对象来实现的Schema

意味着这FieldInspector如果您正在处理引用(也称为命名模型),通常应该避免使用视图或特定于方法的S,因为您永远不会知道哪个视图将是第一个为给定序列化程序生成模式的视图。

重要信息:ModelSerializer从模型生成的小号  嵌套字段ForeignKeys将始终按值输出。如果你想要通过引用行为,你必须明确地设置嵌套字段的序列化器类,而让它不是ModelSerializer自动生成一个;  例如:

class OneSerializer(serializers.ModelSerializer):
   class Meta:
      model = SomeModel
      fields = ('id',)


class AnotherSerializer(serializers.ModelSerializer):
   chilf = OneSerializer()

   class Meta:
      model = SomeParentModel
      fields = ('id', 'child')

另一个由此产生的警告是,任何名为“  NestedSerializer”的序列化程序都将被强制内联,它除非有ref_name明确集合。

你可能感兴趣的:(API接口)