๐ DRF์์๋ CBV๋ฅผ ์ฌ์ฉํ ์์ ๊ฐ ๋ง์ ์๋ก์ด ๋ฐฉ์๋ ๋ฐฐ์๋ณด๊ณ ์ CBV๋ฅผ ๊ณต๋ถํด๋ณด๋ ค๊ณ ํฉ๋๋ค. ๋น์ทํ๋ฉด์๋ ์ฐจ์ด์ ์ด ๋ช ํํด๋ณด์ฌ ์๊ธฐ ์ ์ ์ ๋ฆฌํด๋ณด๋ฉด์ ๊ณต๋ถํ ๋ด์ฉ์ ๋๋ค!
APIView
์ด ํด๋์ค๋ Django์ ์ผ๋ฐ์ ์ธ View๋ฅผ ํ์ฅํ์ฌ API ์์ฒญ์ ์ฒ๋ฆฌํ๋๋ก ๋์ต๋๋ค. get()
, post()
, put()
, delete()
๊ฐ์ HTTP ๋ฉ์๋๋ฅผ ๋ช
์์ ์ผ๋ก ์ ์ํ์ฌ ์ฌ์ฉ์๊ฐ ์ง์ ํธ๋ค๋ฌ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
- ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ทฐ ํด๋์ค.
- HTTP ๋ฉ์๋๋ฅผ ์ง์ ์ ์ํด์ผ ํจ.
- serializer, queryset ๋ฑ์ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ผ ํจ.
class MyAPIView(APIView):
def get(self, request):
# GET ์์ฒญ ์ฒ๋ฆฌ
def post(self, request):
# POST ์์ฒญ ์ฒ๋ฆฌ
GenericAPIView
GenericAPIView๋ APIView๋ฅผ ํ์ฅํ ํด๋์ค์
๋๋ค. APIView๋ณด๋ค ์ข ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉฐ ์ง์ ์ ์ผ๋ก CRUD ๊ธฐ๋ฅ์ ์ฒ๋ฆฌํ์ง๋ ์์ง๋ง, queryset
๊ณผ serializer_class
, lookup_field
๊ฐ์ ์์ฑ์ ๊ธฐ๋ณธ์ผ๋ก ์ค์ ํ์ฌ ๊ณตํต ๋์์ ๊ตฌํํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ข ๋ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- queryset, serializer_class ๋ฑ์ ์์ฑ์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต.
- get_object(), get_queryset(), get_serializer() ๋ฑ์ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ฌ ๊ฐ์ฒด ์กฐํ์ ์ง๋ ฌํ ์์
์ ์ฝ๊ฒ ํ ์ ์์.
- ๋ ๊ตฌ์ฒด์ ์ธ ๋ทฐ๋ฅผ ๋ง๋ค ์ ์๋ ๊ธฐ๋ฐ์ ์ ๊ณต.
class MyGenericAPIView(GenericAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
def get(self, request, *args, **kwargs):
# GET ์์ฒญ ์ฒ๋ฆฌ
Mixin
- CreateModelMixin: ๊ฐ์ฒด ์์ฑ ์ฒ๋ฆฌ
- RetrieveModelMixin: ๊ฐ์ฒด ์กฐํ ์ฒ๋ฆฌ
- UpdateModelMixin: ๊ฐ์ฒด ์์ ์ฒ๋ฆฌ
- DestroyModelMixin: ๊ฐ์ฒด ์ญ์ ์ฒ๋ฆฌ
- ListModelMixin: ๊ฐ์ฒด ๋ฆฌ์คํธ ์กฐํ ์ฒ๋ฆฌ
mixin์ GenericAPIView์ ํจ๊ป ์ฌ์ฉํ๋ฉฐ ๋ ๊ตฌ์ฒด์ ์ธ ๋์์ ๊ตฌํํ ์ ์์ต๋๋ค. mixin๋ list, create, retrieve, update, delete ๊ฐ์ ๊ธฐ๋ฅ์ ๋ฐ๋ก ์ ๊ณตํด์ฃผ๋ฉฐ ์ด๋ฅผ ์กฐํฉํ์ฌ ํ์์ ๋ง๋ ๋ทฐ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
class PostListMixins(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
def get(self, request, *args, **kwargs):
return self.list(request)
def post(self, request, *args, **kwargs):
return self.create(request)
class PostDetailMixins(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request)
def put(self, request, *args, **kwargs):
return self.update(request)
def delete(self, request, *args, **kwargs):
return self.delete(request)
concrete generic view
- ListAPIView: ๋ฐ์ดํฐ ๋ฆฌ์คํธ๋ฅผ ์กฐํํ ๋ ์ฌ์ฉ
- RetrieveAPIView: ํน์ ๊ฐ์ฒด๋ฅผ ์กฐํํ ๋ ์ฌ์ฉ
- CreateAPIView: ๋ฐ์ดํฐ๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ
- UpdateAPIView: ๋ฐ์ดํฐ๋ฅผ ์์ ํ ๋ ์ฌ์ฉ
- DestroyAPIView: ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ๋ ์ฌ์ฉ
- ListCreateAPIView: ๋ฐ์ดํฐ ๋ฆฌ์คํธ ์กฐํ ๋ฐ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ
- RetrieveUpdateAPIView: ํน์ ๊ฐ์ฒด๋ฅผ ์กฐํํ๊ณ ์์ ํ ๋ ์ฌ์ฉ
- RetrieveDestroyAPIView: ํน์ ๊ฐ์ฒด๋ฅผ ์กฐํํ๊ณ ์ญ์ ํ ๋ ์ฌ์ฉ
- RetrieveUpdateDestroyAPIView: ํน์ ๊ฐ์ฒด๋ฅผ ์กฐํ, ์์ , ์ญ์ ํ ๋ ์ฌ์ฉ
DRF์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ์ ์ธ ์ ๋ค๋ฆญ ๋ทฐ(generic view)๋ฅผ ์ข ๋ ๊ตฌ์ฒดํํ(view with specific behavior) ํด๋์ค์ ๋๋ค. DRF๋ ์ฌ๋ฌ ๊ฐ์ง CRUD ์์ ์ ์ฝ๊ฒ ์ํํ ์ ์๋๋ก ๋ฏธ๋ฆฌ ์ ์๋ ๊ตฌ์ฒด์ ์ธ ์ ๋ค๋ฆญ ๋ทฐ๋ค์ ์ ๊ณตํฉ๋๋ค.
class PostListGenericAPIView(generics.ListCreateAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
class PostDetailGenericAPIView(generics.RetrieveUpdateDestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
ViewSet
ViewSet์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ๋ฌ HTTP ๋ฉ์๋(GET, POST, PUT, DELETE ๋ฑ)์ ๋ํ ํธ๋ค๋ฌ๋ฅผ ํ๋์ ํด๋์ค์์ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ค๊ณ๋ ํด๋์ค์ ๋๋ค. ViewSet์ ์ฌ์ฉํ๋ฉด ๋ ๊ฐ๊ฒฐํ๊ณ ๊ตฌ์กฐํ๋ ์ฝ๋๋ก CRUD API๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
ViewSet
ViewSet์ ์ผ๋ฐ์ ์ธ APIView์ ๋น์ทํ์ง๋ง, ์ฌ๋ฌ ๋์์ ํ๋์ ํด๋์ค์์ ์ฒ๋ฆฌํ๋๋ก ์ค๊ณ๋์์ต๋๋ค. ์ผ๋ฐ์ ์ธ APIView๊ฐ ๊ฐ ๋ฉ์๋(get()
, post()
๋ฑ)๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ๋ ๋ฐฉ์์ด๋ผ๋ฉด ViewSet์ ๊ทธ ๋์์ ๋ง๋ ํน๋ณํ ๋ฉ์๋๋ค(list()
, retrieve()
, create()
๋ฑ)์ ์ ๊ณตํฉ๋๋ค.
์ฃผ์ ๋ฉ์๋
- list(): GET ์์ฒญ์ผ๋ก ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํ
- retrieve(): ํน์ ๊ฐ์ฒด๋ฅผ ๋ฐํ (์์ธ ์กฐํ)
- create(): ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑ
- update(): ๊ฐ์ฒด๋ฅผ ์ ๋ฐ์ดํธ
- destroy(): ๊ฐ์ฒด๋ฅผ ์ญ์
class MyViewSet(viewsets.ViewSet):
def list(self, request):
# ๋ฆฌ์คํธ ์กฐํ ๋ก์ง
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
# ํน์ ๊ฐ์ฒด ์กฐํ ๋ก์ง
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)
GenericViewSet
Generic ViewSet์ DRF์์ ViewSet๊ณผ GenericAPIView์ ๊ธฐ๋ฅ์ ๊ฒฐํฉํ ํด๋์ค๋ก ๊ธฐ๋ณธ์ ์ผ๋ก ViewSet์ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด๋ฉด์๋ ์ ๋ค๋ฆญ ๋ทฐ์ ์ ์ฐ์ฑ์ ์ ๊ณตํฉ๋๋ค. GenericAPIView์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์์๋ฐ์ผ๋ฉด์ ViewSet์ ๋ผ์ฐํ ๋ฐ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ๊ฒฐํฉํ ๊ตฌ์กฐ๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค. Generic ViewSet ์์ฒด๋ CRUD ์์ ์ ์ง์ ์ ๊ณตํ์ง ์๊ธฐ ๋๋ฌธ์ ํ์ํ mixin์ ๊ฒฐํฉํ์ฌ ๊ตฌํํ ์ ์์ต๋๋ค.
class MyModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
ModelViewSet
ModelViewSet์ ViewSet์ ํ์ฅ์ผ๋ก create()
, retrieve()
, update()
, partial_update()
, destroy()
, list()
๋ฉ์๋๊ฐ ์๋์ผ๋ก ๊ตฌํ๋ฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ธ๊ณผ ์ฐ๊ฒฐ๋์ด ์์ผ๋ฉฐ queryset
๊ณผ serializer_class
๋ฅผ ์ง์ ํ๋ฉด ์๋์ผ๋ก ๋ชจ๋ CRUD ๋์์ด ๊ตฌํ๋ฉ๋๋ค.
class MyModelViewSet(viewsets.ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
ReadOnlyModelViewSet
ModelViewSet์ ์ฝ๊ธฐ ์ ์ฉ ๋ฒ์ ์
๋๋ค. list()
์ retrieve()
๋ฉ์๋๋ง ์ ๊ณตํ๋ฉฐ CRUD ์์
์ ํ์ง ์์ต๋๋ค.
class MyReadOnlyModelViewSet(viewsets.ReadOnlyModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer