본문으로 바로가기

DRF 객체를 copy 하기

category 장고MTV 6년 전

Django RestFramework 에서 copy 기능을 구현

 

(현재 다른 미션이 있어서 일단은 코드 포스팅만을 진행)

 

□ views.py

class ProductCopyInstance(APIView):
    serializer_class = ProductSerializer

    def get_object(self, pk):
        try:
            return Product.objects.get(pk=pk)
        except Product.DoestNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        response = self.get_object(pk=pk)
        serializer = ProductSerializer(response)
        return Response(serializer.data)

    def post(self, request, pk, format=None, **kwargs):
        """
        복사하여 새로운 객체를 만들어주기 때문에 POST 메서드로 사용하기 도전
        그럼 instance=request.data 와 같이 어떤 객체인지를 먼저 알게 해줘야 할 듯
        """
        # 현재 해당하는 객체의 pk 가 무엇인지까지 확인
        # kwargs 는 해당하는 딕셔너리에서 key 값만을 불러옴
        # POST 메서드에서 data 를 불러오면 새로 입력한 값들이 들어오기 때문에 .data 는 피해야 함
        # original_data = self.kwargs.get('pk', '')
        # 생성하려는 객체를 만들기 위해 우선 Product 모델에서 불러오기(아직 직렬화 상태 아님)
        product = Product.objects.get(pk=pk)
        product.pk = None
        # 직렬화 상태(serializer) 로 만듦
        # 이 클래스에서 get 메서드를 통해 들어온 request.data 를 data 로 받아 직렬화
        # 매직메서드 __dict__ 의 사용방법은 느낌적으로 옳지 않은 것 같지만 일단은 구현을 위해 사용
        serializer = ProductSerializer(product, data=product.__dict__)
        additional_data = serializer
        if additional_data.is_valid():
            # save() 함수를 사용하기 위해서는 is_valid() 가 필수(아니면 에러 발생)
            additional_data.save()
            return Response(additional_data.data, status=status.HTTP_201_CREATED)
        return Response(additional_data.errors, status=status.HTTP_400_BAD_REQUEST)

 

□ Django ORM CookBook 에서 아이디어를 얻은 인스턴스를 copy 하는 방법

>> Product.objects.all().count()
# 4

>> coffee = Product.objects.first()

>> coffee.pk = None

>> coffee.save()

>> Product.objects.all().count()
# 5

 

□ urls.py

- 가장 논의가 많이 될 것 같은 해당 자원에 접근하는 URI 이다.

- 주석에서도 설명한 듯이 자원에 대해 POST, GET, PUT, DELETE 는 REST 에서 확인할 수 있지만 객체를 copy 한다는 메서드가 정의되어 있지가 않다. 그렇기 때문에 RESTful 의 원칙에는 위배될 수 있지만 실수를 줄이고 명시적으로 하기 위해서는 이 방법이 맞지 않을까라고 지금 순간에는 생각한다.

 

urlpatterns = [
    path('products/', views.ProductList.as_view()),
    # 자원에 대한 행위(method) 를 보여주지 않는 것이 원칙이라고 한다.
    # 그러나 copy 를 명시하지 않으면 DRF 에서는 어떤 기능을 하는지 구현을 해봐야 알 수 있다는 것
    path('products/<int:pk>/copy/', views.ProductCopyInstance.as_view()),
    path('products/<int:pk>/', views.ProductDetail.as_view()),
]

 

 

장고MTV카테고리의 다른글

django normalize_email  (0) 2019.06.21
list view 구현(multiple queryset list view)  (0) 2019.05.16
장고 한줄 정리  (0) 2019.05.15
장고 CRUD 기능 구현(4) Delete  (0) 2019.05.07
장고 CRUD 기능 구현(3) Update  (0) 2019.05.07