DRF API : 지난 포스트에서 DRF 시리얼라이져를 사용해서 모델에 맞는 직렬화를 자동으로 해주고 API로 응답하는 방법을 정리했습니다. 이번에는 지난 정리에 이어서 DRF를 이용해서 CRUD에 대한 API를 생성하는 법을 공부하고 정리해보았습니다.

DRF 개념 정리

API 설계

다음과 같이 API를 설계했다고 가정하고 이를 어떻게 DRF로 구현하는지 공부해보았습니다.

NameMethodEndpoint
Article 목록 조회GET/articles/
Article 상세 조회GET/articles/<int:article_id>/
Article 생성POST/articles/
Article 수정PUT/articles/<int:article_id>/
Article 삭제DELETE/articles/<int:article_id>/

목록 조회 DRF API

urls.py

from django.urls import path
from . import views

app_name = "articles"
urlpatterns = [
    path("", views.article_list, name="article_list"),
]

serializer.py

from rest_framework import serializers
from .models import Article


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

views.py

from django.shortcuts import get_object_or_404
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import ArticleSerializer
from .models import Article


@api_view(["GET"])
def article_list(request):
    articles = get_object_or_404(Article)
    serializer = ArticleSerializer(articles, many=True)
    return Response(serializer.data)

API 요청 결과

상세 조회 DRF API

urls.py

from django.urls import path
from . import views

app_name = "articles"
urlpatterns = [
    path("", views.article_list, name="article_list"),
    path("<int:article_pk>/", views.article_detail, name="article_detail"),
]

views.py

@api_view(["GET"])
def article_detail(request, article_pk):
    article = get_object_or_404(Article, pk=article_pk)
    serializer = ArticleSerializer(article)
    return Response(serializer.data)

API 요청

정상적인 요청

모델에 없는 데이터 요청

생성 DRF API

urls.py

from django.urls import path
from . import views

app_name = "articles"
urlpatterns = [
    path("", views.article_list, name="article_list"),
    path("<int:article_pk>/", views.article_detail, name="article_detail"),
]

views.py

@api_view(["GET", "POST"])
def article_list(request):
    if request.method == "GET":
        articles = Article.objects.all()
        serializer = ArticleSerializer(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=201)
        return Response(serializer.errors, status=400)

API 요청

HTTP 상태코드를 자동으로 반환

상태코드를 명시적으로 입력

from rest_framework import status

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

삭제 DRF API

urls.py

views.py

@api_view(["GET", "DELETE"])
def article_detail(request, article_pk):
    article = get_object_or_404(Article, pk=pk)
    if request.method == "GET":
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

    elif request.method == "DELETE":
        article.delete()
        data = {"delete": f"Article({article_pk}) is deleted."}
        return Response(data, status=status.HTTP_200_OK)

api 요청

수정 DRF API

views.py

@api_view(["GET", "PUT", "DELETE"])
def article_detail(request, article_pk):
    article = get_object_or_404(Articles, pk=article_pk)
    if request.method == "GET":
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

    elif request.method == "PUT":
        article = get_object_or_404(Articles, pk=article_pk)
        serializer = ArticleSerializer(article, data=request.data, partial=True)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data)

    elif request.method == "DELETE":
        article.delete()
        data = {"delete": f"Article({article_pk}) is deleted."}
        return Response(data, status=status.HTTP_200_OK)

마치며

생성, 조회, 수정, 삭제에 대한 API를 DRF로 생성해보았습니다. DRF가 참 편하네요.. 역시 만들어져 있는 걸 가져다 쓰는 게 참 편한 것 같습니다.

또한 API를 만들면서 느낀점인데 PostMan을 통해서 손쉽게 결과를 보면서 연습하니까 굉장히 좋은 것 같습니다.

다만 주의점은 브라우저에서는 trail slash(/)를 명시적으로 입력하지 않아도 자동으로 붙여서 요청을 보내주지만 PostMan에서는 trail slash를 명시적으로 붙여줘야 정상 작동 합니다.

해당 사실을 몰라서 코드를 뜯어보면서 1시간을 보낸 것 같네요…ㅎ

참고하면 좋은 글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다


목차