ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • drf_spectacular를 사용한 api docs 만들기
    Django 2022. 11. 20. 17:11

    목차

      서론

      필자가 drf_spectacularf를 사용하여 만들었던 docs 페이지를 기억하기 위해 작성하는 페이지입니다.
      찾으시는 내용이 없을 수 있습니다.
      또한 정확히 알지 않고 필자의 경험으로만 이루어져 있기 때문에 없는 내용 및 틀린 내용이 존재할 수 있습니다.

      본론

      1. drf-spectacular settings

      settings.py에 API docs에 보여질 title, description, version을 지정할 수 있습니다.
      이외의 기타 설정값들도 지정할수 있으니 링크 를 참조하시길 바랍니다.

      SPECTACULAR_SETTINGS = {
          'TITLE': 'TITLE',
          'DESCRIPTION': 'DESCRIPTION',
          'VERSION': '1.0.0',
      }

      2. extend_schema

      - 기본 사용법

      사용할 api의 method 함수 부분에 @extend_schema 데코레이터를 추가하여 사용할 수 있습니다.

      class TistoryView(APIView):
      
          @extend_schema(
          ...
          )
          def get(self, request):
              ...


      3. tags, summary, description

      tags: swagger에 어떤 부분에 tag 되어있을건지 정한다.
      기본적으로 django의 app name에따라 default로 정해진다.

      summary: url 옆에 요약줄 부분에 내용을 쓸 수 있다.

      description: 접은글을 펴면 상단에 위치한 description을 볼 수 있다.

      class TistoryView(APIView):
      
          @extend_schema(
              tags=['files'],
              summary="요약줄",
              description="""설명란<br/>
                  html 태그를 사용할 수도 있습니다. """,
          )
          def get(self, request):
              ...


      tas, summary, description 적용 이미지

      4. parameters

      paramters를 사용하여 url의 parameter를 추가할 수 있습니다.
      또한 아래 이미지와 같이 parameter를 추가하여, 테스트 할 수 있습니다.

      class TistoryView(APIView):
      
          @extend_schema(
              ...
              parameters=[
                  OpenApiParameter(
                      name="name",
                      type=str,
                      description="description",
                      required=False,
                  )
              ]
          )
          def get(self, request):
              pass


      5. request

      아래와 같이 request에 Serailizer를 사용하여 이 api에서 받을 request 데이터를 자동으로 정할 수 있습니다.
      그러나 이런 Serializer를 사용한 docs 자동화는 serialier_class를 사용 할 수 있는 GenericAPIView 이상부터 가능합니다.
      즉 일반 APIView는 사용이 불가능 합니다.

      class TistoryView(GenericAPIView):
          serializer_class = TistorySerializer
      
          @extend_schema(
              request=TistorySerializer,
          )
          def post(self, request, *args, **kwargs):
              pass



      물론 다른 방법으로 inline_serializer를 사용하여 정의할 수 있습니다.

      class TistoryView(APIView):
      
          @extend_schema(
              request=inline_serializer(
                  name='inline serializer',
                  fields={
                      "name": serializers.CharField(default="name"),
                      "integer": serializers.IntegerField(default=100)
                  }
              )
          )
          def post(self, request, *args, **kwargs):
              pass
      

      비교를 위해 default 값을 넣었습니다

      inline_serializer를 사용하면, 일반적인 APIView를 사용해도 request 값을 정할 수 있습니다.

      6. responses

      responses를 사용하여 api의 response를 정할 수 있습니다.
      dictionary형태로 status_code: response 형태로 적용합니다.
      그러나 중복된 status_code의 여러 가지 형태의 response는 보여줄 수 없습니다.

      class TistoryView(GenericAPIView):
          serializer_class = TistorySerializer
      
          @extend_schema(
              request=None,
              responses={
                  200: TistorySerializer,
                  400: None
              }
          )
          def post(self, request, *args, **kwargs):
              pass

      7. examples

      examples를 사용하여 API의 예시를 추가할 수 있습니다.
      OpenAPiExaple을 사용하여 넣을 수 있습니다.
      parameters, requests에도 사용이 가능하나 필자는 response를 사용한 예시를 보여드리겠습니다.

      name: 키값(중복된 값이 있을시, 마지막으로 정의된 값으로 고정됩니다)
      summary: 선택 목록에 보일 내용
      value: response value
      status_code: response에서 고정될 status_code
      response_only: response에만 들어갈 내용인지

      class TistoryView(GenericAPIView):
          serializer_class = TistorySerializer
      
          @extend_schema(
              request=None,
              responses={
                  200: TistorySerializer,
                  400: OpenApiTypes.OBJECT
              },
              examples=[
                  OpenApiExample(
                      name="400(1)",
                      summary="400(1)",
                      value={
                          "message": "400(1)",
                      },
                      status_codes=["400"],
                      response_only=True
                  ),
                  OpenApiExample(
                      name="400(2)",
                      summary="400(2)",
                      value={
                          "message": "400(2)",
                      },
                      status_codes=["400"],
                      response_only=True
                  ),
              ]
          )
          def post(self, request, *args, **kwargs):
              pass

      주의할 사항으로는 responses에서 400의 값이 None이라면 examples가 적용되지 않으므로 OpenApiTypes.OBJECT를 넣었습니다.
      어떤 값이든 들어가면 됩니다.

      추가 팁 (파일 업로드)

      실패 사례

      먼저 일반적으로 사용되는 FileField drf-spectacular에서 적용되지 않습니다.

      class TistoryView(APIView):
          @extend_schema(
              request=inline_serializer(
                  name="upload example",
                  fields={
                      "file": serializers.FileField(),
                  },
              )
          )
          def post(self, request, *args, **kwargs):
              pass


      성공사례

      spectacular settings에 COMPONENT_SPLIT_REQUEST: True와
      APIView에 parser_classes를 추가하면 파일 업로드가 가능해집니다.

      settings.py

      SPECTACULAR_SETTINGS = {
          ...
          'COMPONENT_SPLIT_REQUEST': True
      }

      views.py

      class TistoryView(APIView):
          parser_classes = (MultiPartParser,)
          @extend_schema(
              request=inline_serializer(
                  name="upload example",
                  fields={
                      "file": serializers.FileField(),
                  },
              )
          )
          def post(self, request, *args, **kwargs):
              pass

      파일 선택하는 버튼이 생성되었습니다

      댓글

    Designed by Tistory.