drf-spectacular는 django에서 문서 작성할 때 유용하다. 시리얼라이저를 사용해서 요청, 응답에 대한 문서를 작성할 수 있고 문서에서 보여 줄 예시, 기본 값도 설정할 수 있다.
데코레이터를 사용해야해서 문서를 작성하다보면 view 메서드보다 데코레이터가 더 커지면서 배보다 배꼽이 더 커지는 경우가 생긴다.
데코레이터를 다른 파일로 이동시켜서 간소화하자.
수정 전 view 메서드에 달려 있는 장황한 데코레이터.
class GetRealEstatesOnSearchView(ListAPIView):
@extend_schema(
summary="keyword로 부동산 조회",
description="keyword로 부동산 조회",
parameters=[
OpenApiParameter(
name="deal_type",
type=str,
location=OpenApiParameter.PATH,
description="deal, jeonse, monthly_rent",
required=True,
examples=[
OpenApiExample(
name="매매",
description="매매 타입",
value="deal",
),
OpenApiExample(
name="전세",
description="전세 타입",
value="jeonse",
),
OpenApiExample(
name="월세",
description="월세 타입",
value="monthly_rent",
),
],
),
OpenApiParameter(
name="keyword",
type=str,
location=OpenApiParameter.QUERY,
description="검색어",
required=True,
examples=[
OpenApiExample(
name="강남",
description="강남",
value="강남",
),
OpenApiExample(
name="하안미리",
description="하안미리",
value="하안미리",
),
OpenApiExample(
name="부산",
description="부산",
value="부산",
),
],
),
OpenApiParameter(
name="limit",
type=int,
location=OpenApiParameter.QUERY,
description="몇 개 보여줄 지 결정, regions는 3개로 고정",
required=False,
default=10,
examples=[
OpenApiExample(
name="최소 limit",
description="최소 limit",
value="10",
),
OpenApiExample(
name="최대 limit",
description="최대 limit",
value="30",
),
],
),
],
request=GetRealEstatesOnSearchRequestSerializer,
responses={
200: PolymorphicProxySerializer(
component_name="RealEstatesAndRegions",
serializers=[GetRealEstatesAndRegionsOnSearchResponseSerializer],
resource_type_field_name=None,
),
400: OpenApiResponse(description="bad request"),
404: OpenApiResponse(description="not found"),
},
)
# @jwt_authenticator
def get(
self,
request: Request,
*args,
**kwargs,
) -> JsonResponse:
pass
schema 파일을 따로 만들어서 데코레이터를 추출한다.
real_estate_view_schema.py
from drf_spectacular.utils import (
extend_schema,
OpenApiResponse,
OpenApiParameter,
PolymorphicProxySerializer,
OpenApiExample,
)
from real_estate.serializers import (
GetRealEstatesAndRegionsOnSearchResponseSerializer,
GetRealEstatesOnSearchRequestSerializer,
)
def get_real_estates_on_search_view_get_decorator(view_function):
decorated_view_function = extend_schema(
summary="keyword로 부동산 조회",
description="keyword로 부동산 조회",
parameters=[
OpenApiParameter(
name="deal_type",
type=str,
location=OpenApiParameter.PATH,
description="deal, jeonse, monthly_rent",
required=True,
examples=[
OpenApiExample(
name="매매",
description="매매 타입",
value="deal",
),
OpenApiExample(
name="전세",
description="전세 타입",
value="jeonse",
),
OpenApiExample(
name="월세",
description="월세 타입",
value="monthly_rent",
),
],
),
OpenApiParameter(
name="keyword",
type=str,
location=OpenApiParameter.QUERY,
description="검색어",
required=True,
examples=[
OpenApiExample(
name="강남",
description="강남",
value="강남",
),
OpenApiExample(
name="하안미리",
description="하안미리",
value="하안미리",
),
OpenApiExample(
name="부산",
description="부산",
value="부산",
),
],
),
OpenApiParameter(
name="limit",
type=int,
location=OpenApiParameter.QUERY,
description="몇 개 보여줄 지 결정, regions는 3개로 고정",
required=False,
default=10,
examples=[
OpenApiExample(
name="최소 limit",
description="최소 limit",
value="10",
),
OpenApiExample(
name="최대 limit",
description="최대 limit",
value="30",
),
],
),
],
request=GetRealEstatesOnSearchRequestSerializer,
responses={
200: PolymorphicProxySerializer(
component_name="RealEstatesAndRegions",
serializers=[GetRealEstatesAndRegionsOnSearchResponseSerializer],
resource_type_field_name=None,
),
400: OpenApiResponse(description="bad request"),
404: OpenApiResponse(description="not found"),
},
)(view_function)
return decorated_view_function
@get_real_estates_on_search_view_get_decorator
만 남아서 깔끔해졌다.
from real_estate.views.schema.real_estate_view_schema import (
get_real_estates_on_search_view_get_decorator,
)
class GetRealEstatesOnSearchView(ListAPIView):
@get_real_estates_on_search_view_get_decorator
def get(
self,
request: Request,
*args,
**kwargs,
) -> JsonResponse:
pass