[DRF] 함수형 기반 View
오늘 DRF에 대해서 블로그를 보다가 CBV 클래스형 기반 view는 블로그를 작성했는데 함수형 기반 view를 작성하지 않은것을 발견하고 후다닥 블로그를 정리해 보려고한다.
가장 기본적으로 DRF의 공식문서를 참고해서 블로그를 작성을 해보겠다.
함수형 기반의 view는 api_view함수를 데코레이터 해서 사용을 하게 된다.
코드를 살펴보자.
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Post, comment
from .serializers import PostSerializer, CommentSerializer
@api_view(['GET', 'POST'])
def post_list(request, format=None):
if request.method == 'GET':
post = Post.objects.all()
serializer = Postserilaizer(post, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = Postserializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
일단 기본적인 post_list의 api를 작성했다. 여기에는 GET, POST 메서드에 응답을 주는 것으로 되어있으며 GET메서드가 오면 모든 데이터를 반환해주며 POST 요청이 오면 serializer에 request.data를 담아주고 그것의 유효성검증을 한후에 유효성 검증을 통과한다면 DB에 저장을 하고 아니면 에러를 띄우는 api를 만들었다.
이제 post_detail 함수를 작성을 해보자.
@api_view(['GET', 'PUT', 'DELETE'])
def post_detail(request, pk, format=None):
"""
Retrieve, update or delete a code snippet.
"""
try:
post = Post.objects.get(pk=pk)
except Post.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = PostSerializer(post)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = PostSerializer(post, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
post.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['GET', 'PUT', 'DELETE'])
def post_detail(request, title):
# 위에 코드와 같이 pk가 아닌 title을 넣는다면 title값을 요청으로 받게 되고 요청으로 들어온 title값을 DB에서 찾아서
# 응답으로 반환을 하게 된다.
위의 코드는 이제 프론트엔드에서 url의 엔드포인트에 pk를 요청으로 넘겨주면 pk를 받아서 처리를 하게 되는 api를 만들어 놓은것이다.
요청 받은 pk에 대한 post만 GET요청시 보내주며 PUT은 post의 수정을 해주고 DELETE는 pk로 받은 post를 삭제해주는 api가 된다.
try-except 구문을 통해서 예외처리를 진행해 두었다. 요청을 받은 post의 pk값이 DB에 없는 pk면 Post.objects.get(pk=pk)메서드가 돌아가면서 DoeseNotExist의 에러를 띄우게 된다. 이것은 get( )함수의 특징이다. 이것은 전 블로그에 정리를 해놨다. 그렇기에 그에대한 예외처리를 해놓은 것이다.
- 함수형 View에서 primary_key말고 요청받은 다른 컬럼 데이터에 대해 DB에서 꺼내오는 방법
# views.py
@api_view(['GET'])
def getProductsName(request, product_name):
try:
data = Products.objects.get(product_name=product_name)
serializer = Productsserializer(data, many=False)
return Response(serializer.data)
except Products.DoesNotExist:
response = {
'message' : '찾으시는 결과가 없습니다.'
}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
# urls.py
urlpatterns = [
path('productsdata/', ProductsList.as_view(), name='Products'),
path('productsdata/<str:product_name>/', getProductsName),
]
urlpatterns = format_suffix_patterns(urlpatterns)
위에 코드는 product_name을 엔드포인트에서 프론트엔드에게 요청을 받는다면 요청받은 product_name에 대한 데이터를 DB에서 꺼내주는 코드를 짠 것이다. 만약 없을 때도 존재하기에 예외처리를 해놨다.
여기서 또 알수 있는것은 위의 예제에서는 post = Post.objects.get(pk=pk)에서 pk이지만 만약 post의 모델에서 name이나 title과 같은 다른 데이터 feature를 가지고 있다면 그것을 써도 된다.
필자가 만든 Post는 title과 contente가 있는데 post = Post.objects.get(title=title)이렇게 작성을 한다면 요청으로 온 title에 대해서 DB에서 요청으로온 title과 같은 title을 찾고 그것에 대한 값을 응답으로 주게 된다.
주의해야 할점!!
매우중요!!! 위의 예제는 함수형 View에서만 작동한다. 클래스형 기반 View에서는 pk이외의 다른 feature를 넣으면 에러가 뜬다. 클래스형 기반 View에서는 get_queryset()이라는 GenericAPIview에 내장으로 들어가 있는 함수를 따로 정의해주어야 한다!!! 무조건 기억하기!!!! @@
이제 urls.py는 어떤 식으로 구성되는지 보자.
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from .views import post_list, post_detail
urlpatterns = [
path('posts/', views.post_list),
path('posts/<int:pk>/', views.post_detail),
# path('posts/<str:title>/', views.post_detail)
]
urlpatterns = format_suffix_patterns(urlpatterns)
이것 또한 CBV를 할때 많이 다뤘기 때문에 익숙한 것을 볼 수 있다.
path('posts/<str:title>/', views.post_detail)이 코드는 요청을 title로 받고싶다면 쓸 수 있는 코드이다. 즉 엔드포인트에 title을 받음으로써 title값을 요청으로 받고 그에 맞는 값을 DB에서 찾아서 응답으로 주는 것이다. --> 응용하는 법 (이것은 함수형 View에서만 작동한다. 함수형 View의 장점이다!!!!! 클래스형 기반 View에서는 안된다!!! 무조건 기억하기!!!)
이로써 함수형 기반의 View도 정리를 끝냈다!!!
@+@+