Python/DRF

[DRF] APIView로 CRUD 구현하기

emhaki 2023. 1. 12. 15:46
728x90
반응형
SMALL

APIview의 기본적인 골격은 아래와 같다.

class Class_name(APIView):
	def method_name(self, request, format=None):
    	# 해당 HTTP method를 어떻게 동작시킬지 정의

method_name으로는 HTTP method인 get, post, delete 등이 존재한다. APIView를 상속 받아서 원하는 기능을 구현하기 위한 HTTP method를 구현하면 된다.

models.py

from django.db import models
from django.conf import settings

# Create your models here.

class Blog(models.Model):
  title = models.CharField(max_length=100)
  body = models.TextField()

Blog라는 모델에서 게시판 기능을 위해 title과 body라는 field를 만들어준다.

 

serializers.py

from .models import Blog
from rest_framework import serializers

class BlogSerializer(serializers.ModelSerializer):
  class Meta:
    model = Blog
    fields = '__all__'

DRF에서 사용되는 serializers.py를 프로젝트 앱 폴더 내에서 만들어준다. serializers는 주어진 데이터를 직렬화하는 역할을 한다고 한다. 설치한 rest_framework를 통해 serializers를 import 해준다. 

views.py

전체코드

from .models import Blog
from .serializer import BlogSerializer
# APIView를 사용하기 위해 import
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404


# Blog list를 보여줄 때
class BlogList(APIView):

  def get(self, request):
    blogs = Blog.objects.all()
    # 여러 개의 객체를 serialization하기 위해 many = True로 설정
    serializer = BlogSerializer(blogs, many = True)
    return Response(serializer.data)

  # 새로운 blog 글을 작성할 때 
  def post(self, request):
    # request.data는 사용자의 입력 데이터
    serializer = BlogSerializer(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)

# Blog detail을 보여주는 역할
class BlogDetail(APIView):
  
  # blog 객체 가져오기
  def get_object(self, pk): # get_object 선언
    try:
      return Blog.objects.get(pk=pk)
    except Blog.DoesNotExist:
      raise Http404
  
  # blog의 detail 보기
  def get(self, request, pk, format=None):
    blog = self.get_object(pk)
    serializer = BlogSerializer(blog)
    return Response(serializer.data)

  # blog 수정하기
  def put(self, request, pk, format=None):
    blog = self.get_object(pk)
    serializer = BlogSerializer(blog, data=request.data)
    if serializer.is_valid():
      serializer.save()
      return Response(serializer.data)
    return Response(serializer.error, status=status.HTTP_400_BAD_REQUEST)
  
  # blog 삭제하기
  def delete(self, request, pk, format=None):
    blog = self.get_object(pk)
    blog.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

blog list

# Blog list를 보여줄 때
class BlogList(APIView):

  def get(self, request):
    blogs = Blog.objects.all()
    # 여러 개의 객체를 serialization하기 위해 many = True로 설정
    serializer = BlogSerializer(blogs, many = True)
    return Response(serializer.data)

  # 새로운 blog 글을 작성할 때 
  def post(self, request):
    # request.data는 사용자의 입력 데이터
    serializer = BlogSerializer(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)

BlogList 클래스 안에 get과 post 함수를 정의해준다. get은 전체 목록을 보여주기 위한 코드이며, post는 새로운 blog 객체를 등록하기 위한 코드이다.

Blog detail

# Blog detail을 보여주는 역할
class BlogDetail(APIView):
  
  # blog 객체 가져오기
  def get_object(self, pk): # get_object 선언
    try:
      return Blog.objects.get(pk=pk)
    except Blog.DoesNotExist:
      raise Http404
  
  # blog의 detail 보기
  def get(self, request, pk, format=None):
    blog = self.get_object(pk)
    serializer = BlogSerializer(blog)
    return Response(serializer.data)

  # blog 수정하기
  def put(self, request, pk, format=None):
    blog = self.get_object(pk)
    serializer = BlogSerializer(blog, data=request.data)
    if serializer.is_valid():
      serializer.save()
      return Response(serializer.data)
    return Response(serializer.error, status=status.HTTP_400_BAD_REQUEST)
  
  # blog 삭제하기
  def delete(self, request, pk, format=None):
    blog = self.get_object(pk)
    blog.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

BlogDetail 클래스에는 객체를 가져오기 위한 get_object를 만들어주고, pk값이 정상적으로 넘어왔다면 Blog.object를 리턴, 아니라면 404 에러를 보내준다. 만들어놓은 get_object를 통해 기본적인 CRD 기능을 만들어준다. 

urls.py

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

urlpatterns = [
    path('blog/', views.BlogList.as_view()),
    path('blog/<int:pk>', views.BlogDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

프로젝트 앱 안에 urls.py를 생성해 path를 등록해준다.

이후에 app 폴더 내부의 url을 프로젝트 내부의 urls.py에 등록해준다.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls'))
]
python manage.py makemigrations
python manage.py migrate
python manage.py runserver

새로 작성한 model을 마이그레이션 시켜주고 웹 서버를 실행 시켜준다.

 http://localhost:8000/blog/

위와 같은 url로 들어가게 되면 Blog List가 보이게 된다.

위와 같이 객체를 생성해서 POST를 눌러주게 되면 오른쪽과 같이 JSON 형태로 blog 객체가 생성되는 걸 볼 수 있다.

생성된 객체의 pk값을 설정한 url로 입력해 들어가게 되면 PUT을 통해 수정과 DELETE 버튼을 통해 삭제도 할 수 있다. 하지만 APIView를 사용하게 되면 특정 함수를 반복해서 사용하게 되고 결국 코드가 길어지게 된다.

 

참고

https://wisdom-990629.tistory.com/m/entry/DRF-APIView%EB%A1%9C-CRUD-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0

728x90
반응형