API란?

API란 "Application Programming Interface"의 약자로, 프로그램들이 상호작용할 수 있는 인터페이스를 제공하는 것을 의미한다. Django의 API는 주로 HTTP 프로토콜을 통해 데이터를 주고받는 RESTful API 형식이며, 구축하기 위해서는 다음과 같은 주요 구성 요소가 필요하다

  1. 모델(Model): Django의 모델은 데이터베이스의 테이블과 매핑된다. 데이터베이스에서 데이터를 읽고 쓰는 데 사용되는 ORM(Object-Relational Mapping)을 통해 모델을 정의한다. 각 모델은 데이터베이스의 테이블과 필드에 해당하며, 이를 통해 데이터의 구조를 정의하고 조작할 수 있다.
  2. 시리얼라이저(Serializer): 시리얼라이저는 Django의 모델 데이터를 JSON 또는 XML과 같은 직렬화된 형식으로 변환해주는 역할을 한다.
  3. 뷰(View): Django의 뷰는 HTTP 요청을 받아 처리하는 로직을 담당한다. API의 뷰는 요청을 받아 데이터를 읽고 쓰는 등의 작업을 수행하고, 그 결과를 응답으로 반환한다.
  4. URL 패턴(URL Patterns): URL 패턴은 클라이언트가 API에 접근할 수 있는 엔드포인트를 정의한다. 각 엔드포인트는 특정한 HTTP 요청(Method)과 URL에 매핑되며, 해당 요청을 처리할 뷰를 지정한다.

 

GET

질문 목록을 가져와 API를 통해 제공하는 코드이다.

from polls.models import Question
from polls_api.serializers import QuestionSerializer
from rest_framework.response import Response
from rest_framework.decorators import api_view

@api_view()
def question_list(request):
    questions = Question.objects.all()
    serializer = QuestionSerializer(questions, many = True)
    return Response(serializer.data)
  1. @api_view(): question_list 함수를 API 뷰로 변환하는 장식자. 아무값도 넣지 않을경우에는 GET 메서드가 기본으로 호출된다.
  2. questions = Question.objects.all(): 데이터베이스에서 모든 질문을 가져온다. Question 모델의 모든 인스턴스를 쿼리셋으로 가져오는것이다.
  3. serializer = QuestionSerializer(questions, many=True): 질문 쿼리셋을 시리얼라이저에 전달하여 질문 데이터를 JSON 형식으로 직렬화. many=True는 다수의 객체를 직렬화할 때 사용.
  4. return Response(serializer.data): 시리얼라이저에서 얻은 데이터를 포함하는 Response 객체를 반환. 

 

POST

질문 목록 조회 및 새로운 질문 등록을 위한 코드이다.

from rest_framework.decorators import api_view
from polls.models import Question
from polls_api.serializers import QuestionSerializer
from rest_framework.response import Response
from rest_framework import status

@api_view(['GET','POST'])
def question_list(request):
    if request.method == 'GET':
        questions = Question.objects.all()
        serializer = QuestionSerializer(questions, many = True)
        return Response(serializer.data)
    
    if request.method == 'POST':
        serializer = QuestionSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  1. @api_view(['GET', 'POST']): question_list 함수를 GET 및 POST 요청을 처리할 수 있는 API 뷰로 정의.
  2. GET 요청 처리:
    • if request.method == 'GET':: 요청이 GET 메서드인 경우 위의 코드와 동일하게 진행
  3. POST 요청 처리:
    • if request.method == 'POST': : 요청이 POST 메서드인 경우,
      • serializer = QuestionSerializer(data=request.data): 요청으로부터 데이터를 받아 새로운 질문 객체 생성.
      • if serializer.is_valid(): : 시리얼라이저가 유효한 경우,
        • serializer.save(): 시리얼라이저에서 질문을 생성하고 저장.
        • return Response(serializer.data, status=status.HTTP_201_CREATED): 상태 코드와 함께 생성된 질문을 포함하는 응답 객체를 반환
      • else: : 유효하지 않은 경우,
        • return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST): 에러 메시지를 포함하는 응답 객체를 반환

 

PUT (==UPDATE)

특정 질문의 세부 정보를 반환하고, 질문 내용을 업데이트하는 코드

@api_view(['GET', 'PUT'])
def question_detail(request, id):
    question = get_object_or_404(Question, pk=id)
    
    if request.method == 'GET':
        serializer = QuestionSerializer(question)
        return Response(serializer.data)

    if request.method == 'PUT':
        serializer = QuestionSerializer(question, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:    
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  1. question = get_object_or_404(Question, pk=id): 데이터베이스에서 주어진 ID에 해당하는 질문을 가져오며, 만약 해당 ID에 해당하는 질문이 없다면 404 에러를 발생
  2. GET 요청 처리:
    • if request.method == 'GET':: 요청이 GET 메서드인 경우,
      • serializer = QuestionSerializer(question): 질문 객체를 시리얼라이저에 전달하여 JSON 형식으로 직렬화.
      • return Response(serializer.data): 시리얼라이저에서 얻은 데이터를 포함하는 Response 객체를 반환.
  3. PUT 요청 처리:
    • if request.method == 'PUT':: 요청이 PUT 메서드인 경우,
      • serializer = QuestionSerializer(question, data=request.data): 요청으로부터 데이터를 받아 질문 객체를 업데이트
      • if serializer.is_valid():: 시리얼라이저가 유효한 경우,
        • serializer.save(): 시리얼라이저에서 질문을 업데이트하고 저장.
        • return Response(serializer.data, status=status.HTTP_200_OK): 업데이트된 질문을 포함하는 응답 객체를 반환.
      • else:: 유효하지 않은 경우,
        • return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST): 에러 메시지를 포함하는 응답 객체를 반환

 

DELETE

질문을 삭제하는 코드

from django.shortcuts import get_object_or_404

@api_view(['GET', 'PUT', 'DELETE'])
def question_detail(request, id):
    question = get_object_or_404(Question, pk=id)
    
    ...
    
    if request.method == 'DELETE':
        question.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 

Class based view

데코레이터를 사용하지 않고 클래스로 나누어서 API를 작성하는것도 가능하다. 두가지 방법 모두 동일한 기능을 제공하지만 클래스를 사용하여 작성할 경우 코드가 더 깔끔해진다. 또한 상속 역시 가능해서 코드의 재사용성이 증가한다.

from rest_framework.views import APIView
from rest_framework.decorators import api_view
from polls.models import Question
from polls_api.serializer import QuestionSerializer
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404


class QuestionList(APIView):
    def get(self, request):
        questions = Question.objects.all()
        serializer = QuestionSerializer(questions, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = QuestionSerializer(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)

class QuestionDetail(APIView):
    def get(self, request, id):
        question = get_object_or_404(Question, pk=id)
        serializer = QuestionSerializer(question)
        return Response(serializer.data)

    def put(self, request, id):
        question = get_object_or_404(Question, pk=id)
        serializer = QuestionSerializer(question, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:    
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
    def delete(self, request, id):
        question = get_object_or_404(Question, pk=id)
        question.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 

Generic based view


Django에서 제공하는 Generic View는 일반적인 웹 개발 작업에서 반복되는 패턴을 미리 구현해 놓은 재사용 가능한 뷰 클래스들을 말한다. 이러한 Generic Views를 사용하면 개발자가 뷰를 작성할 때 일정한 패턴을 따라야 하는 번거로움을 줄일 수 있고, 코드의 재사용성과 유지보수성을 높일 수 있다. 

from polls.models import Question
from polls_api.serializers import QuestionSerializer
from rest_framework import generics

class QuestionList(generics.ListCreateAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer

class QuestionDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer

 

제네릭뷰에 대한 더 자세한 내용을 알고싶다면 다음 사이트를 참고하면 좋을듯하다. https://kimcoder.tistory.com/581

 

[Django] 클래스형 뷰와 제네릭 뷰 소개

장고에서는 뷰를 클래스로도 작성할 수 있으며, 함수형 뷰보다는 클래스형 뷰가 더 이점이 많다. 이번 포스팅에서는 클래스형 뷰와 제네릭 뷰에 대한 감을 잡아보자. 1. 클래스형 뷰의 장점 - 다

kimcoder.tistory.com

 

'Dev Tool > Django' 카테고리의 다른 글

[Django] Serilalizer 알아보기  (1) 2024.04.10
[Django] 뷰(Views)와 템플릿(Templates)  (0) 2024.04.10
[Django] Shell 사용하기  (0) 2024.04.09
[Django] model 만들고 활용하기  (0) 2024.04.08
[Django] Django App 생성하기  (0) 2024.04.08