DRF로 APIView, Json 응답뷰 만들기
2022. 7. 11. 23:02ㆍ강의 정리/Django REST Framework
반응형
장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!
ModelSerializer를 통한 JSON 직렬화
_Serializer / ModelSerializer은 Form / ModelForm과 유사합니다.
-> 역할 면에서 Serializer은 POST 요청만 처리하는 Form
- 둘의 공통점
- 폼 필드 지정 혹은 모델로부터 읽어오기.
- 입력된 데이터에 대한 유효성 검사를 통해 저장합니다.
- 둘의 차이점
- Form / ModelForm : Form태그가 포함된 HTML을 생성합니다.
- Serializer / ModelSerializer : Form 데이터가 포함된 JSON 문자열을 생성합니다.
Serializer를 통한 뷰처리(DRF를 사용하지 않을 때)
from rest_framework.serializers import ModelSerializer
# Post모델에 대한 ModelSerializer 정의
class PostSerializer(ModelSerializer):
class Meta:
model = Post
fields = '__all__'
# Views
serializer = PostSerializer(data=request.POST)
if serializer.is_valid():
# 유효성 검사에 통과한 값들을 전달
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)
- Form 생성자의 첫번째 인자는 data이지만, Serializer 생성자의 첫번째 인자는 instance이다.
DRF의 기본 CBV인 APIView
- APIView 클래스 혹은 @api_view장식자
- View에 여러 기본 속성을 부여한다.
- renderer_classes: 직렬화 class 다수
- parser_classes: 비직렬화 class 다수
- authentication_classes: 인증 class 다수 -> 유저를 식별하는 것
- throttle_classes: 사용량 제한 class 다수(호출 제한)
- permission_classes: 권한 class 다수 -> 유저를 식별하고 나서 각 자원에 대해 접근 레벨을 정의
- content_negotiation_class: 요청에 따라 적절한 직렬화/비직렬화 class를 선택하는 class
- metadata_class: 메타 정보를 처리하는 class
- versioning_class: 요청에서 API버전 정보를 감지하는 class
- 각 옵션의 디폴트 값
- renderer_classes
- rest_framework.renderers.JSONRenderer : JSON 직렬화
- rest_framework.renderers.TemplateHTMLRenderer : HTML 페이지 직렬화
- parser_classes
- rest_framework.parsers.JSONParser : JSON 포맷 처리
- rest_framework.parsers.FormParser
- rest_framework.parsers.MultiPartParser
- authentication_classes
- rest_framework.authentication.SessionAuthentication : 세션에 기반한 인증
- rest_framework.authentication.BasicAuthentication : HTTP Basic 인증
- throttle_classes
- 빈 튜플 (디폴트로는 요청 횟수 제한이 설정 되어 있지 않음)
- permission_classes
- rest_framework.permissions.AllowAny : 누구라도 접근 허용
- content_negotiation_class
- rest_framework.negotiation.DefaultContentNegotiation
- 같은 URL로의 요청이지만, JSON응답을 요구하는 것이냐 / HTML응답을 요구하는 것인지 판단
- metadata_class
- rest_framework.metadata.SimpleMetadata
- versioning_class
- None: API 버전 정보를 탐지하지 않겠다.
- 요청 URL에서, GET인자에서, HEADER에서 버전 정보를 탐지하여 해당 버전의 API뷰가 호출되도록 합니다.
- renderer_classes
APIView와 @api_view
- APIView : 클래스 기반 뷰//상속 받아야 함
- @api_view : 함수 기반 뷰를 위한 장식자
APIView
- 하나의 CBV 이므로 -> 하나의 URL만 처리 가능
- 그러나 ApiView를 좀더 표준화-> Generic
- Generic을 좀더 합친 것: ViewSet
- ViewSet은 여러개의 URL의 대응이 가능하다.
- 즉 ApiView와 Generic은 하나의 get, post, put, delete의 url만 매핑 가능하다면 ViewSet은 두개의 url 매핑 가능
- 각 method(get, post, put, delete)에 맞게 멤버함수를 구현하면, 해당 method 요청이 들어올 때 호출. 호출 이전 단계(initial)에서 다음을 처리함
- // APIView를 상속받을 때 자동으로 처리되는 작업들
- 직렬화 / 비직렬화 처리(JSON 등)
- 인증 체크
- 사용량 제한 체크: 호출 허용량 범위인지 체크
- 권한 클래스 지정: 비인증/인증 유저에 대해 해당 API 호출을 허용할 것인지를 결정
- 요청된 API버전 문자열을 탐지하여, request.version에 저장
클래스 형태) APIView 구현 샘플
get, post등을 직접 구현 하였으나 직렬화, 인증 등은 APIView에 포함되어있고, 우리는 그것을 상속 했으므로 직접 구현하지 않아도 된다.
list / create
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Post
from .serializers import PostSerializer
class PostListAPIView(**APIView**):
def get(self, request):
qs = Post.objects.all()
serializer = PostSerializer(qs, many=True)
return Response(serializer.data)
def post(self, request):
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
detail / update / delete
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Post
from .serializers import PostSerializer
class PostDetailAPIView(**APIView**):
def get_object(self, pk):
return get_object_or_404(Post, pk=pk)
def get(self, request, pk, format=None):
post = self.get_object(pk)
serializer = PostSerializer(post)
return Response(serializer.data)
def put(self, request, pk):
post = self.get_object(pk)
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)
def delete(self, request, pk):
post = self.get_object(pk)
post.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- 위 메소드들은 무슨 프로젝트를 진행하더라도 거의 비슷하게 작성되고, 반복된다. 이를 패턴화 한게 generics이고, generics를 합쳐서 구조화 시킨 것을 viewset이라 한다.
# rest_framework/views.py
from django.views.decorators.csrf import csrf_exempt
class APIView(View):
# …
@classmethod
def as_view(cls, **initkwargs):
# …
**return csrf_exempt(view)
- 뷰가 csrf_exempt 장식자로 이미 감싸져있기에 POST 요청에서 csrf token 체크를 하지 않습니다.
- 이를 이해하기 위해서 파이썬 장식자를 공부할 필요가 있다!!!
함수 형태) @api_view 장식자 구현 샘플
- 하나의 작업만을 구현코자 할 때 @api_view를 쓰면 편리하다.
List / create
from django.http import get_object_or_404
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .models import Post
from .serializers import PostSerializer
# 나는 어떤 인자를 지원하겠다라고 명시
# 인자를 비우면 매칭되지 않음
**@api_view**(['GET', 'POST'])
def post_list(request):
if request.method == 'GET':
serializer = PostSerializer(Post.objects.all(), many=True)
return Response(serializer.data)
else:
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
- 함수형 뷰에서는 각 요청을 if문으로 처리한다.
detail / update / delete
from rest_framework.decorators import api_view
from rest_framework.response import Response
**@api_view**(['GET', 'PUT', 'DELETE'])
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
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)
else:
post.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
https://www.django-rest-framework.org/api-guide/fields/
https://velog.io/@kmnkit/drf-rwonly
- serializer field를 통해 읽기만 해야하는 필드, 쓰기만 해야하는 필드, 둘 다 해야하는 필드로 나눌 수 있다.
혼자만의 깨달음
왜 DRF의 페이지에서는 해당 페이지로 보내진 API(JSON)만 보이고, 기존 Django에서 보이던 페이지들이 왜 안보이지라고 생각했었는데 정말 무지했다.
DRF의 목적은 프론트단에 API를 보내주는게 목적이거늘 Django처럼 풀스택만을 지원한다고 생각했던 것이 패착이었다.
이 이유로 DRF의 view단에서 return response를 보내줄 때 html을 render하지 않고 data만 보내준다.
반응형
'강의 정리 > Django REST Framework' 카테고리의 다른 글
DRF ViewSet과 Router (0) | 2022.07.13 |
---|---|
DRF mixins 상속을 통한 APIView (0) | 2022.07.12 |
Django JSON 직렬화 (0) | 2022.03.22 |
Django JSON 응답뷰 (0) | 2022.03.12 |
Django API와 REST (0) | 2022.03.10 |