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

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

覆蓋將操作的描述,並記錄沒有正文和給定描述的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明確的集合。

 

注: 本文作爲個人學習筆記,如有侵權,請聯繫刪除

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章