Django REST Framework/DRF 일반

[DRF] 공식 문서 - Metadata 정리

bluebamus 2024. 1. 22.

 1. Metadata

   - REST 프레임워크는 OPTIONS 요청에 대해 API가 어떻게 응답해야 하는지 결정하는 구성 가능한 메커니즘을 포함하고 있습니다. 이를 통해 API 스키마나 다른 리소스 정보를 반환할 수 있다.

   - 현재 HTTP OPTIONS 요청에 대해 반환되어야 하는 응답 스타일에 대해 널리 통용되는 규칙은 없습니다. 따라서 우리는 유용한 정보를 반환하는 임시 방식의 응답을 제공한다.

   - 다음은 기본적으로 반환되는 정보를 보여주는 예시 응답이다.

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json

{
    "name": "To Do List",
    "description": "List existing 'To Do' items, or create a new item.",
    "renders": [
        "application/json",
        "text/html"
    ],
    "parses": [
        "application/json",
        "application/x-www-form-urlencoded",
        "multipart/form-data"
    ],
    "actions": {
        "POST": {
            "note": {
                "type": "string",
                "required": false,
                "read_only": false,
                "label": "title",
                "max_length": 100
            }
        }
    }
}

 

   1) 메타데이터 체계 설정(Setting the metadata scheme)

      - 'DEFAULT_METADATA_CLASS' 설정 키를 사용하여 메타데이터 클래스를 전역적으로 설정할 수 있다.

REST_FRAMEWORK = {
    'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata'
}

 

      - 또는 뷰마다 개별적으로 메타데이터 클래스를 설정할 수도 있다.

class APIRoot(APIView):
    metadata_class = APIRootMetadata

    def get(self, request, format=None):
        return Response({
            ...
        })

 

      - REST 프레임워크 패키지에는 SimpleMetadata라는 하나의 메타데이터 클래스 구현체만 포함되어 있다. 다른 스타일을 사용하려면 사용자 정의 메타데이터 클래스를 구현해야 한다.

 

   2) 스키마 엔드포인트 생성(Creating schema endpoints)

      - 일반적인 GET 요청으로 액세스되는 스키마 엔드포인트를 생성하는 특정 요구 사항이 있다면, 메타데이터 API를 재사용하는 것을 고려할 수 있다.

      - 예를 들어, 다음과 같은 추가적인 route를 뷰셋에 사용하여 링크 가능한 스키마 엔드포인트를 제공할 수 있다.

@action(methods=['GET'], detail=False)
def api_schema(self, request):
    meta = self.metadata_class()
    data = meta.determine_metadata(request, self)
    return Response(data)

 

      - 이러한 접근 방식을 선택하는 이유는 여러 가지가 있을 수 있다. 그 중 하나는 OPTIONS 응답이 캐시할 수 없다는 점이다.

         - are not cacheable : https://www.mnot.net/blog/2012/10/29/NO_OPTIONS

 

 2. 사용자 정의 메타데이터 클래스(Custom metadata classes)

   - 사용자 정의 메타데이터 클래스를 제공하려면 BaseMetadata를 재정의하고 determine_metadata(self, request, view) 메서드를 구현해야 한다.

   - 반환할 수 있는 유용한 정보로는 JSON 스키마와 같은 형식으로 스키마 정보를 반환하거나, 디버그 정보를 관리자 사용자에게 반환하는 등의 작업이 있을 수 있다.

      - JSON schema : https://json-schema.org/

 

   1) Example

      - 다음 클래스는 OPTIONS 요청에 반환되는 정보를 제한하는 데 사용할 수 있다.

class MinimalMetadata(BaseMetadata):
    """
    Don't include field and other information for `OPTIONS` requests.
    Just return the name and description.
    """
    def determine_metadata(self, request, view):
        return {
            'name': view.get_view_name(),
            'description': view.get_view_description()
        }

 

      - 그런 다음 설정을 구성하여 이 사용자 정의 클래스를 사용하면 된다.

REST_FRAMEWORK = {
    'DEFAULT_METADATA_CLASS': 'myproject.apps.core.MinimalMetadata'
}

 

 3. Third party packages

   1) DRF-schema-adapter

      - drf-schema-adapter는 프런트엔드 프레임워크와 라이브러리에 스키마 정보를 제공하기 쉽게하는 도구 세트이다. 메타데이터 mixin과 2개의 메타데이터 클래스, 여러 개의 어댑터를 제공하여 json-schema 및 다양한 라이브러리에서 읽을 수 있는 스키마 정보를 생성하는 데 적합하다.

      - 또한 특정 프런트엔드와 함께 작업하기 위해 직접 어댑터를 작성할 수도 있다. 이 경우 해당 스키마 정보를 json 파일로 내보내는 내보내기 도구도 제공된다.

 

- drf-schema-adapter : https://github.com/drf-forms/drf-schema-adapter

- json-schema : https://json-schema.org/

 

      - 예시

from rest_framework.views import APIView
from rest_framework.response import Response
from drf_schema_adapter.metadata import SchemaMetadataMixin
from drf_schema_adapter.metadata import JsonSchemaMetadataClass

class MyAPIView(SchemaMetadataMixin, APIView):
    """
    MyAPIView는 스키마 메타데이터를 제공하는 APIView입니다.
    """

    metadata_class = JsonSchemaMetadataClass
    """
    metadata_class는 JsonSchemaMetadataClass를 사용하여 JSON 스키마 메타데이터를 생성합니다.
    """

    def get(self, request):
        """
        GET 요청을 처리하는 메소드입니다.
        """

        data = {
            'message': 'Hello, world!',
            'count': 10,
            'results': ['item1', 'item2', 'item3']
        }
        return Response(data)

    def post(self, request):
        """
        POST 요청을 처리하는 메소드입니다.
        """

        # Request body 스키마 정보를 생성합니다.
        request_schema = {
            'type': 'object',
            'properties': {
                'name': {'type': 'string'},
                'age': {'type': 'integer'}
            },
            'required': ['name']
        }

        # Response body 스키마 정보를 생성합니다.
        response_schema = {
            'type': 'object',
            'properties': {
                'message': {'type': 'string'}
            }
        }

        # 스키마 정보를 메타데이터에 등록합니다.
        self.set_request_body_schema(request, request_schema)
        self.set_response_body_schema(response_schema)

        # 요청 처리 로직을 구현합니다.
        name = request.data.get('name')
        age = request.data.get('age')
        message = f"Hello, {name}! You are {age} years old."
        data = {
            'message': message
        }
        return Response(data)

 

      - 위의 코드는 DRF-schema-adapter를 사용하여 스키마 정보를 제공하는 예시이다. MyAPIView 클래스는 APIView를 상속하고, SchemaMetadataMixin을 사용하여 스키마 메타데이터를 제공한다. metadata_class 속성을 설정하여 JSON 스키마 메타데이터를 생성하는 JsonSchemaMetadataClass를 사용한다.

      - GET 요청을 처리하는 get 메소드와 POST 요청을 처리하는 post 메소드가 구현되어 있다. POST 요청의 경우, Request body와 Response body의 스키마 정보를 생성하고, set_request_body_schema와 set_response_body_schema 메소드를 사용하여 메타데이터에 등록한다. 이후 요청 데이터를 처리하고 응답을 반환한다.

      - 이와 같이 DRF-schema-adapter를 사용하면 프론트엔드 프레임워크 및 라이브러리에 스키마 정보를 제공할 수 있다. 필요에 따라 특정 프론트엔드와 함께 작동하기 위해 사용자 정의 어댑터를 작성하거나, 스키마 정보를 JSON 파일로 내보내는 기능을 활용할 수도 있다.

 

- 공식 사이트 문서 : https://www.django-rest-framework.org/api-guide/metadata/

 

Metadata - Django REST framework

 

www.django-rest-framework.org

 

댓글