Django : Rest API, Serialization

김재훈·2024년 4월 26일

Django

목록 보기
14/15

Django REST framework

  • DRF
  • Django에서 Restful API 서버를 쉽게 구축할 수 있도록 도와주는 오픈소스 라이브러리

POSTMAN

  • Postman 설치
  • Postman 이란?
    • API를 구축하고 사용하기 위한 플랫폼
    • API를 빠르게 만들 수 있는 여러 도구 및 기능을 제공
    • Postman 외에도 여러가지 있으며, VSCode Extension으로도 구현되어 있음.

URL과 HTTP requests methods 설계

GETPOSTPUTDELETE
articles/전체 글 조회글 작성
articles/1/1번 글 조회1번 글 수정1번 글 삭제

GET

  • 게시글 데이터 목록 조회하기
  • 게시글 데이터 목록을 제공하는 ArticleListSerializer 정의
# articles/serializers.py

from rest_framework import serializers
from .models import Article

class ArticleListSerializer(serializers.ModelSerializer):
	class Meta:
    	model = Article
        fields = ('id', 'title', 'content',)

Serialization

  • 직렬화
  • 여러 시스템에서 활용하기 위해 데이터 구조나 객체 상태를 나중에 재구성할 수 있는 포맷으로 변환하는 과정
  • 데이터 구조나 객체 상태를 나중에 재구성할 수 있는 포맷으로 변환하는 과정

Serializer

  • Serialization을 진행하여 Serialized data를 반환해주는 클래스

ModelSerializer

  • Django 모델과 연결된 Serializer 클래스
  • many 옵션
    • Serialize 대상이 QuerySet인 경우 입력
  • data 속성
    • Serialized data 객체에서 실제 데이터를 추출

'api_view' decorator

  • DRF view 함수에서는 필수로 작성되며 view 함수를 실행하기 전 HTTP 메서드를 확인
  • 기본적으로 GET 메서드만 허용되며 다른 메서드 요청에 대해서는 405 Method Not Allowd로 응답
  • DRF view 함수가 응답해야 하는 HTTP 메서드 목록을 작성

일반 Serializer와 달리 사용자 입력 데이터를 받아 자동으로 모델 필드에 맞추어 Serialization을 진행

# articles/urls.py

urlpatterns = [
	path('articles/', views.article_list),
]

# articles/views.py

from rest_framework.response import Response
from rest_framework.decorators import api_view

from .models import Article
from .serializers import ArticleListSerializer

@api_view(['GET'])
def article_list(request):
	articles = Article.objects.all()
    serializer = ArticleListSerializer(articles, many=True)
    return Response(serializer.data)

과거 view 함수와의 비교

  • 똑같은 데이터를
    HTML에 출력되도록 페이지와 함께 응답했던 과거의 view 함수,
    JSON 데이터로 serialization하여 페이지 없이 응답하는 현재의 view 함수
# articles/serializers.py

class ArticleSerializer(serializers.ModelSerializer):
	class Meta:
    	model = Article
        fields = '__all__'

POST

  • article_list view 함수 구조 변경 (method에 따른 분기처리)
from rest_framework import status

@api_view(['GET', 'POST']
def article_list(request):
	if request.method == 'GET':
    	articles = Article.objects.all()
        serializer = ArticleListSerializer(articles, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
    	serializer = ArticleSerializer(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)

DELETE

  • 게시글 데이터 삭제하기
    • 요청에 대한 데이터 삭제가 성공했을 경우는 204 No Content 응답
# aricles/views.py

@api_view(['GET', 'DELETE'])
def article_detail(request, article_pk):
	article = Article.objects.get(pk=article_pk)
   	if request.method == 'GET':
    	serializer = ArticleSerializer(article)
        return Response(serializer.data)
    elif request.method == 'DELETE':
    	article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

PUT

@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
	...
    
    elif request.method == 'PUT':
    	serializer = ArticleSerializer(article, data=request.data, partial=True)
        
        if serializer.is_valid():
        	serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

'partial' argument

  • 부분 업데이트를 허용하기 위한 인자
  • 예를 들어 partial 인자 값이 False일 경우 게시글 title만을 수정하려고 해도 반드시 content 값도 요청 시 함께 전송해야 함
  • 기본적으로 serializer는 모든 필수 필드에 대한 값을 전달받기 때문
    • 즉, 수정하지 않는 다른 필드 데이터도 모두 전송해야 하며 그렇지 않으면 유효성 검사에서 오류가 발생
    • ArticleSerializer(article, data=request.data, partial=True)

raise_exception

  • is_valid()의 선택 인자
  • 유효성 검사를 통과하지 못할 경우 ValidationError 예외를 발생시킴
  • DRF에서 제공하는 기본 예외 처리기에 의해 자동으로 처리되며 기본적으로 HTTP 400 응답을 반환
# articles/views.py

@api_view(['GET', 'POST'])
def article_list(request):
	...
    elif request.method == 'POST':
    	serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
        	serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        # return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

0개의 댓글