# APIvew와 ViewSet으로 Response하기
이전에 포스팅했던 내용의 확장으로 News 리스트를 출력하고 detail페이지까지 넘겨주는 방법에 대해 정리해보고자 한다.
🔎 views.py
class NewsViewSet(viewsets.ModelViewSet):
queryset = News.objects.all()
serializer_class = NewsSerializer
# 뉴스 리스트
def list(self, request, *args, **kwargs):
game_date = request.query_params.get('game_date')
queryset = self.filter_queryset(self.get_queryset())
if game_date is not None:
queryset = queryset.filter(game_date=game_date)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
이전 포스팅에 게임 일자를 기준으로 NewsViewSet을 만들었다. queryset에는 News모델의 모든 객체를 가져오는 쿼리셋이 저장되고 serializer_class 변수에는 News 모델을 직렬화하는데 사용되는 NewsSerializer가 지정된다.
list 메소드에서는 GET 요청을 처리하며 ' game_date'쿼리 파라미터를 받아 해당하는 날짜의 뉴스만 필터링하여 결과를 반환한다. queryset 변수에서 get_queryset() 메소드를 사용하여 모든 객체를 가져오고 fillter_queryset() 메소드를 사용하여 가져온 쿼리셋을 필터링한다.
if문에서는 game_date가 None값이 아니라면 filter 메소드를 사용해 game_date 필드가 game_date 쿼리 파라미터 값과 일치하는 객체만 쿼리셋에 남기고 필터링한다.
serializer 변수에는 get_serializer() 메소드를 사용해 queryset에 대한 직렬화된 데이터를 생성한다. many매개변수는 여러 객체를 직렬화할 때 True로 설정해야 한다고 한다. 이후 Response객체에 serializer.data를 반환해준다.
🔎 views.py
class NewsViewSet(viewsets.ModelViewSet):
queryset = News.objects.all()
serializer_class = NewsSerializer
# 뉴스 리스트
def list(self, request, *args, **kwargs):
game_date = request.query_params.get('game_date')
queryset = self.filter_queryset(self.get_queryset())
if game_date is not None:
queryset = queryset.filter(game_date=game_date)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
# detail 페이지
def retrieve(self, request, pk=None):
queryset = News.objects.all()
news = get_object_or_404(queryset, pk=pk)
serializer = NewsSerializer(news)
return Response(serializer.data)
여기에 이제 retrieve 메소드를 추가했는데 retrieve 메소드는 뉴스리스트를 클릭했을 때 디테일 페이지로 넘겨주는 역할을 한다. retrieve 메소드는 ViewSet 클래스의 메소드 중 하나로 특정 pk값에 해당하는, 여기에서는 News 모델 인스턴스를 반환한다. 뉴스의 pk값을 기준으로 get_object_or_404 함수를 실행하고 pk값과 일치하는 객체를 찾거나 404 Not Found를 발생시켜준다. NewsSerializer 클래스에 news를 담아서 serializer에 저장해주고 Response 객체에 담아 반환해준다. 이렇게 하면 NewsViewSet 클래스에서 리스트목록과 뉴스를 클릭했을 때 디테일페이지로까지 한 클래스에 적용할 수 있다.
🔎 urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import NewsViewSet
router = DefaultRouter()
router.register(r'news', NewsViewSet, basename='news')
urlpatterns = [
path('', include(router.urls)),
]
router 변수는 DRF의 DefaultRouter 클래스를 이용해 ViewSet 클래스를 등록하는데 사용된다. router.register 메소드를 이용하여 NewsViewSet 클래스를 news URL과 함께 등록한다. 여기에서 basename 매개변수는 NewsViewSet 클래스의 URL 패턴 이름에 사용되는데 이렇게 URL을 등록하게 되면 NewsViewSet 클래스의 list와 retrieve 메소드가 각각
/news/ 와 /news/{pk}/
로 URL 매핑되어 GET 요청을 처리할 수 있다. router를 사용하면 코드의 반복을 줄일 수 있고, 빠르게 RESTful API를 개발할 수 있다.
router 클래스는 DefaultRouter, SimpleRouter, NestedRouter 등이 있지만 대부분의 경우 DefaultRouter를 사용한다고 한다. DefaultRouter는 CRUD API에 대한 기본적인 URL 패턴을 생성해준다.
참고로 resister() 메소드에는 다음과 같은 매개변수가 있다.
prefix: URL prefix. 기본값은 뷰셋 클래스의 모델 이름
viewset: URL에 매핑될 뷰셋 클래스
basename: URL 패턴 이름의 접두사
공부하다가 정리한 내용이다보니 틀린 내용이 있을 수 있습니다. 틀린점은 알려주시면 감사하겠습니다 :)
'Python > DRF' 카테고리의 다른 글
[DRF] CORS에러 처리하기 (0) | 2023.03.29 |
---|---|
[DRF] 이론 정리(Serializer, REST API) (0) | 2023.03.28 |
[DRF] DB에 저장된 데이터를 APIview와 ViewSet으로 Response하기 (2) | 2023.02.17 |
[DRF] 게시판에 Authentication과 Permission 적용하기 (0) | 2023.01.29 |
[DRF] 게시판 기능(CRUD) 구현하기 (0) | 2023.01.17 |