DRF - AssertionError : get_queryset() ?
현재 회사에서 프로젝트를 진행중인데,,, 자꾸 위와같은 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을 세팅해주면 해결!