Versioning decorator

2023. 8. 21. 09:35Python/Django

설명

Django Versioning을 하기 위한 방법 중 하나로 Decorator를 만들어 Versioning하는 방법을 정리했습니다.

목차

    Django Versioning

    https://www.django-rest-framework.org/api-guide/versioning/

     

    Versioning - Django REST framework

     

    www.django-rest-framework.org

     

    Versioning Decorator 장점

    • API 구현 시 Depth 가 줄어든다.
    • 유지보수가 편해진다
      • 아래 예시는 Serializer 만 변경되지만, 변경 부분이 다수 존재하는 경우 유지보수가 어려워짐
    • 명확한 version 관리 가능 
      • API 에 대해서 Version을 진행했을 때 버전별 API를 명확히 확인 가능

     

    Versioning 기본 사용 예시

    @action(detail=False, methods=['get'])
    def get_api(self, request, pk):
      if request.version == '1.0'
        serializer = PaymentSerializer(data=request.GET.dict())
      else:
        serializer = KakaoPaymentSerializer(data=request.GET.dict())
      
      serializer.is_valid(raise_exception=True)
      return Response(data=serializer.data, status=status.HTTP_200_OK)

     

    Versioning Decorator

    Version decorator 구현

    • 해당하는 version이 없다면 최신버전의 function을 찾아 실행
    from functools import wraps
    
    def version(func):
        @wraps(func)
        def wrapper(viewset, request, *args, **kwargs):
            version = request.version
            if not version:
                return func(viewset, request, *args, **kwargs)
            try:
                version_function = getattr(viewset, f"{func.__name__}_{version.replace('.', '_')}")
            except:
                r = re.compile(fr'{func.__name__}_(\d+)_(\d+)')
                version_functions = list(filter(r.match, dir(viewset)))
    
                if not version_functions:
                    raise DanbiError('API version 을 잧을 수 없습니다.')
    
                version_functions = sorted(
                    version_functions,
                    key=lambda x: [int(part) if part.isdigit() else part for part in x.split('_')]
                )
                version_function = getattr(viewset, version_functions[-1])
    
            return version_function(request, *args, **kwargs)
        return wrapper

     

    Version decorator 사용 예시

    @version
    @action(detail=False, methods=['get'])
    def get_api(self, request):
      serializer = PaymentSerializer(data=request.GET.dict())
      serializer.is_valid(raise_exception=True)
      return Response(data=response_serializer.data, status=status.HTTP_200_OK)
    
    def get_api_2_0(self, request, pk):
      serializer = KakaoSerialzier(data=request.GET.dict())
      serializer.is_valid(raise_exception=True)
      return Response(data=response_serializer.data, status=status.HTTP_200_OK)

     

     

    추가정보

     

    functools — Higher-order functions and operations on callable objects

    Source code: Lib/functools.py The functools module is for higher-order functions: functions that act on or return other functions. In general, any callable object can be treated as a function for t...

    docs.python.org