[BE 예제] 도서 정보 API

김주언·2022년 7월 4일
0

Django

목록 보기
6/9
post-thumbnail

DRF 개념 학습을 위해 도서 정보를 제공하는 API를 작성한다.
이전의 HelloAPI를 만들었던 프로젝트 그대로 사용


모델

example/models.py 파일에 모델을 정의해준 뒤 마이그레이션을 진행한다.

from django.db import models

# Create your models here

class Book(models.Model):
    bid = models.IntegerField(primary_key=True)
    title = models.CharField(max_length=50)
    author = models.CharField(max_length=50)
    category = models.CharField(max_length=50)
    pages = models.IntegerField()
    price = models.IntegerField()
    published_date = models.DateTimeField()
    description = models.TextField()
python manage.py makemigrations
python manage.py migrate




시리얼라이저

serializer.Serializer

기본적인 시리얼라이저 작성법 예시

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

    def create(self, validated_data):
        return Comment(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        return instance

위 코드를 보면 모델에서 사용했던 필드 내용을 똑같이 반복 작성한다.

시리얼라이저는 파이썬에서 정의한 모델을 (파이썬 객체 데이터를) JSON으로 바꿔주는 변환기이기 때문에 모델 데이터의 어떤 속성을 JSON에 넣어줄지 선언해줘야한다.
따라서 변환하고자 하는 속성을 정의하기 위해서 시리얼라이저에도 개별적으로 필드를 선언해줘야 하기 때문에 코드가 반복적으로 나타나게 된 것

create()update() 함수는 이후에 POST 요청으로 들어온 데이터를 파이썬 객체 데이터로 역직렬화 하여 DB에 넣을 때 사용하는 함수이다. 위처럼 정의해두면 나중에 serializer.save()를 사용하여 간단한 코드로 데이터를 저장할 수 있게된다.

아무튼 반복적이긴한데 필요하다는 뜻
그런데
이런것은.. 귀찮다!

serializer.ModelSerializer

rest_framework가 제공하는 serializer.ModelSerializer를 사용하면 이를 간단한 코드로 작성할 수 있다.

ModelSerializer를 사용하면 다음과 같은 이점이 있다.

  • 모델을 기반으로 자동으로 필드 세트를 생성
  • unique_together 유효성 검사기와 같은 직렬 변환기에 대한 유효성 검사기를 자동으로 생성
  • create()update()의 간단한 기본 구현이 포함되어 있다.

example/serializer.py을 생성한 후 코드를 작성한다.

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['bid', 'title', 'author', 'category', 'pages', 'price', 'published_date', 'description']

아주 간단해졌다 ^^



함수형 뷰와 클래스형 뷰 ( FBV, CBV )

DRF뿐만 아니라 장고에서는 뷰를 함수형(Function Based View)또는 클래스형(Class Based View)으로 작성할 수 있다. FBV와 CBV 작성을 APIview가 도와준다.

APIview는 여러가지 요청의 유형에 대해 동작할 수 있도록 지원한다. 함수형 뷰에서는 @api_view와 같은 데코레이터 형태로 사용하며 클래스형 뷰에서는 APIview 클래스를 상속받는 클래스를 작성하는 형태로 뷰를 생성한다.

이전의 함수형 뷰인 HelloAPI를 클래스형 뷰로 변환하면 아래와 같다.

from django.shortcuts import get_object_or_404
from rest_framework import viewsets, permissions, generics, status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view

class HelloAPI(APIview):
	def get(self, request):
    return Response("hello, world")

gandan

하지만 난 함수형으로 할거다

API 작성

  • GET /book/ : 전체 도서 정보 가져오기
  • GET /book/<bid> : 도서 한권의 정보 가져오기
  • POST /book/ : 도서 정보 등록하기

example/views.py

from django.shortcuts import get_object_or_404
from rest_framework import viewsets, permissions, generics, status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view

# 모델과 시리얼라이저 임포트
from example.models import Book
from example.serializers import BookSerializer


@api_view(['GET'])
def helloAPI(request):
    return Response("hello, world!")

# GET 또는 POST 요청에 대한 처리를 위한 데코레이터 
# GET과 POST 둘 다 동일한 /book/ 주소를 사용하기 때문에 한번에 처리한다
@api_view(['GET', 'POST'])
def booksAPI(request):					
    if request.method == 'GET':			# GET /book/
        books = Book.objects.all()		# DB에 저장된 Book 모델로부터 전체 데이터를 받아온다
        
        # 시리얼라이저에 전체 도서 정보를 전달하여 직렬화한다.
        # many 옵션을 사용하여 한번에 여러 데이터를 전달
        serializer = BookSerializer(books, many=True)		
        
        # 직렬화된 JSON 에서 data 속성을 응답으로 전달하고 상태코드를 설정
        return Response(serializer.data, status=status.HTTP_200_OK)
    
    # POST /book/ 도서 정보를 등록하는 요청
    elif request.method == 'POST':
    
    	# POST요청으로 받은 데이터를 시리얼라이저에 전달
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():	# 전달받은 데이터가 유효한지 확인
        	
            # 모델시리얼라이저의 역직렬화를 통해 save
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        
@api_view(['GET'])
def bookAPI(request, bid):		# GET /book/bid
	# bid를 이용하여 해당 도서를 Book가져온다
    # 해당 도서가 존재하지 않을 시 404 error
    book = get_object_or_404(Book, bid = bid)
    
    # 시리얼라이저에 book 모델을 전달하여 직렬화
    serializer = BookSerializer(book)
    
    # 직렬화된 내용 중 data와 상태코드를 응답으로 전달
    return Response(serializer.data, status=status.HTTP_200_OK)

일반 Serializer의 경우에는 클라이언트로부터 POST 요청으로 들어온 데이터를 (JSON 형태의 문자열) 파이썬 객체 형태로 다시 역직렬화 하기 위해서는 create()update()라는 함수를 작성해야 했었다.

ModelSerializer는 이를 작성하지 않아도 serializer.save() 실행 시 기본적으로 create()를 실행해준다



url 연결

example앱의 urls.py 파일에 코드를 작성한다.

from django.urls import path, include
from .views import helloAPI, booksAPI, bookAPI

urlpatterns = [
    path("hello/", helloAPI),
    path('books/', booksAPI),
    path('book/<int:bid>', bookAPI),

]



실행화면

http://127.0.0.1:8000/example/books/

아직 도서 데이터를 입력하지 않아서 빈 결과가 반환되었고, 해당 주소로 POST 요청을 보낼 수 있다.


도서 정보를 입력한 후 POST 클릭

bid를 이용하여 도서 정보를 출력하기 위해
http://127.0.0.1:8000/example/book/1 를 입력한다.

잘된다~! 끝 ^^

profile
학생 점심을 좀 차리시길 바랍니다

0개의 댓글