drf_spectacular를 사용한 api docs 만들기
목차
서론
필자가 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):
...

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

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
