카테고리 없음

DRF - AssertionError : get_queryset() ?

Jake2 2021. 8. 8. 17:26

현재 회사에서 프로젝트를 진행중인데,,, 자꾸 위와같은 err 가 뜨는 것이 아닌가?

 

안그래도 DRF 와 친해지는 중이라 익숙치 않은데 해당 err를 해결하는데 유독 시간을 많이 쓴거 같다.

 

코드를 공개하긴 어렵지만 대략적인 내용은 이러했다 

class LikeShopViewSet(ModelViewSet):
    serializer_class = LikeShopSerializer
    permission_classes = [IsAuthenticated]

    @transaction.atomic
    @action(detail=True, methods=['DELETE'])
    def list_delete(self, pk):
        likeshop = get_object_or_404(LikeShop, pk=pk)
        shop            = get_object_or_404(Shop, pk=likeshopaccount.shop.id)
        
        likeshop.delete()
        shop.like_count -= 1
        shop.save()
        return Response({'message':'LikeShop Deleted'})

drf 의 ModelViewSet을 상속받은 viewset 에 해당 객체를 삭제하기 위한 코드에서 위와같은 에러가 난것이다 

그러면 여기서 문제는 무엇일까? 

일단 해당 공식문서에서 볼 수 있듯 queryset attribute 나 get_queryset method 가 필요하다. 

package 파일의 get_queryset 부분을 보면 assert self.queryset is None으로 해당 에러의 내용이 정의된 것을 볼 수 있다. get_queryset 은 최초에 호출되고 이후 요청들에  결과가 캐시된다고 한다. 

따라서 해당 queryset을 뭔가 커스텀하여 사용하고 싶을때는 get_queryset을 사용하면 된다고 한다.

나의 프로젝트에서는 커스텀한 결과가 필요한가.? 아니다 그냥 지우면 된다

 

class LikeShopViewSet(ModelViewSet):
    queryset           = LikeShop.objects.all()
    serializer_class   = LikeShopSerializer
    permission_classes = [IsAuthenticated]

    @transaction.atomic
    @action(detail=True, methods=['DELETE'])
    def list_delete(self, pk):
        likeshop = get_object_or_404(LikeShop, pk=pk)
        shop            = get_object_or_404(Shop, pk=likeshopaccount.shop.id)
        
        likeshop.delete()
        shop.like_count -= 1
        shop.save()
        return Response({'message':'LikeShop Deleted'})

그래서 이렇게 작성하고 test 해봤더니 

204 ok 가 뜨긴 했다..

근데 보는것처럼 메세지는 뱉지 않는다... 뭐지?

 

여기서 생각한것이

1) 높은 확률로 해당 list_delete 함수를 거치지 않고 삭제했을 것이고,

2) 그렇다면 상속받은 ModelViewSet 안에 Mixin 안에서 처리가 되었다는 것인데

해당 패키지에서 프린트 찍어보니

해당 instance 가 destroymixin 으로 넘어가서 삭제되는것을 확인 할 수 있었다. 

 

사실 나는 이제 drf 를 사용한지 1주일도 되지 않은 상태에서 해당 err를 해결하며 공부한것이 매우 많아 기분이 좋다.

 

근데 여기서 궁금한것 만약 단순 삭제라면 굳이 delete method 에 대한 함수를 따로 구현 해줄 것 없이 위와 같이 구현하면?

 

django rest framework 라는 이름답게 상당히 restful 하게 api 를 구현 가능한것 같다. 그런데

 

이렇게 되면 Shop의 인스턴스에서 like 숫자를 연산해주는 코드가 필요한데 구현해줄곳이 없다. 

 

그렇다면 내가 작성해준 delete method의 함수를 읽게 하려면? 

 

router.register(r"mylikeshop", LikeShopAccountsViewSet, basename="mylikeshop")

urlpatterns = [
	path('likeshop/<int:pk>/', LikeShopAccount.as_view({'delete' : 'delete'}))
]

다음과 같이 url을 세팅해주면 해결!