2024. 11. 11. 14:25ㆍdjango/Views
Django REST Framework (DRF)은 Django를 기반으로 한 강력한 웹 API 개발 도구입니다. 그 중 APIView
는 DRF에서 가장 기본이 되는 클래스 기반 뷰(Class-Based View)로, HTTP 메서드(GET, POST, PUT, DELETE 등)를 처리하기 위해 def
키워드를 사용하여 메서드를 정의합니다. 이 답변에서는 APIView
에서 사용하는 def
메서드의 정의와 예제를 상세히 설명하겠습니다.
APIView
란?
APIView
는 DRF에서 제공하는 클래스 기반 뷰로, Django의 기본 View
클래스를 확장하여 RESTful API를 쉽게 구축할 수 있도록 도와줍니다. APIView
는 요청(Request)과 응답(Response)을 처리하며, 다양한 HTTP 메서드를 지원합니다.
def
메서드 정의하기
APIView
를 사용할 때, HTTP 메서드에 대응하는 메서드를 def
키워드를 사용하여 클래스 내에 정의합니다. 주요 메서드는 다음과 같습니다:
get
: GET 요청을 처리합니다.post
: POST 요청을 처리합니다.put
: PUT 요청을 처리합니다.patch
: PATCH 요청을 처리합니다.delete
: DELETE 요청을 처리합니다.
각 메서드는 요청을 받아 적절한 응답을 반환하는 역할을 합니다.
주요 메서드 정의 및 예제
1. get
메서드
get
메서드는 클라이언트가 데이터를 조회할 때 사용됩니다. 예를 들어, 특정 객체의 세부 정보를 가져오거나, 객체 목록을 반환할 때 사용됩니다.
예제: 단일 객체 조회
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Book
from .serializers import BookSerializer
class BookDetail(APIView):
def get(self, request, pk, format=None):
try:
book = Book.objects.get(pk=pk)
except Book.DoesNotExist:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = BookSerializer(book)
return Response(serializer.data, status=status.HTTP_200_OK)
설명:
get
메서드는 특정Book
객체를 조회합니다.pk
(Primary Key)를 통해 객체를 찾고, 존재하지 않으면 404 오류를 반환합니다.- 존재하면 직렬화(serializer)를 통해 데이터를 JSON 형식으로 응답합니다.
2. post
메서드
post
메서드는 클라이언트가 새로운 데이터를 생성할 때 사용됩니다. 예를 들어, 새로운 객체를 데이터베이스에 추가할 때 사용됩니다.
예제: 새 객체 생성
class BookList(APIView):
def post(self, request, format=None):
serializer = BookSerializer(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)
설명:
post
메서드는 클라이언트로부터 받은 데이터를 직렬화하고, 유효성을 검사합니다.- 유효하면 객체를 저장하고, 201 Created 상태와 함께 저장된 데이터를 반환합니다.
- 유효하지 않으면 400 Bad Request 상태와 함께 오류를 반환합니다.
3. put
메서드
put
메서드는 클라이언트가 기존 데이터를 전체적으로 업데이트할 때 사용됩니다. 기존 객체를 완전히 교체합니다.
예제: 객체 전체 업데이트
class BookDetail(APIView):
def put(self, request, pk, format=None):
try:
book = Book.objects.get(pk=pk)
except Book.DoesNotExist:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = BookSerializer(book, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
설명:
put
메서드는 특정Book
객체를 찾아 클라이언트로부터 받은 데이터로 업데이트합니다.- 유효성 검사 후 저장하고, 성공 시 업데이트된 데이터를 반환합니다.
- 객체가 존재하지 않으면 404 오류를, 데이터가 유효하지 않으면 400 오류를 반환합니다.
4. patch
메서드
patch
메서드는 클라이언트가 기존 데이터의 일부만 업데이트할 때 사용됩니다. 부분적인 수정이 가능합니다.
예제: 객체 부분 업데이트
class BookDetail(APIView):
def patch(self, request, pk, format=None):
try:
book = Book.objects.get(pk=pk)
except Book.DoesNotExist:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = BookSerializer(book, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
설명:
patch
메서드는 특정Book
객체를 찾아 클라이언트로부터 받은 일부 데이터로 업데이트합니다.partial=True
를 설정하여 부분 업데이트를 허용합니다.- 유효성 검사 후 저장하고, 성공 시 업데이트된 데이터를 반환합니다.
- 객체가 존재하지 않으면 404 오류를, 데이터가 유효하지 않으면 400 오류를 반환합니다.
5. delete
메서드
delete
메서드는 클라이언트가 특정 데이터를 삭제할 때 사용됩니다.
예제: 객체 삭제
class BookDetail(APIView):
def delete(self, request, pk, format=None):
try:
book = Book.objects.get(pk=pk)
except Book.DoesNotExist:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
설명:
delete
메서드는 특정Book
객체를 찾아 삭제합니다.- 삭제가 성공하면 204 No Content 상태를 반환합니다.
- 객체가 존재하지 않으면 404 오류를 반환합니다.
전체 예제: APIView
를 이용한 CRUD API
아래는 Book
모델을 대상으로 한 전체 CRUD(Create, Read, Update, Delete) API 예제입니다.
모델 (models.py
):
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
def __str__(self):
return self.title
직렬화기 (serializers.py
):
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
뷰 (views.py
):
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Book
from .serializers import BookSerializer
class BookList(APIView):
"""
책 목록 조회 및 새로운 책 생성
"""
def get(self, request, format=None):
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, format=None):
serializer = BookSerializer(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 BookDetail(APIView):
"""
특정 책 조회, 업데이트, 삭제
"""
def get_object(self, pk):
try:
return Book.objects.get(pk=pk)
except Book.DoesNotExist:
return None
def get(self, request, pk, format=None):
book = self.get_object(pk)
if not book:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = BookSerializer(book)
return Response(serializer.data, status=status.HTTP_200_OK)
def put(self, request, pk, format=None):
book = self.get_object(pk)
if not book:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = BookSerializer(book, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, pk, format=None):
book = self.get_object(pk)
if not book:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = BookSerializer(book, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
book = self.get_object(pk)
if not book:
return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
설명:
BookList
클래스:get
: 모든 책의 목록을 조회하여 반환합니다.post
: 새로운 책을 생성합니다.
BookDetail
클래스:get
: 특정pk
(Primary Key)를 가진 책을 조회하여 반환합니다.put
: 특정 책을 전체적으로 업데이트합니다.patch
: 특정 책을 부분적으로 업데이트합니다.delete
: 특정 책을 삭제합니다.
URL 설정 (urls.py
):
from django.urls import path
from .views import BookList, BookDetail
urlpatterns = [
path('books/', BookList.as_view(), name='book-list'),
path('books/<int:pk>/', BookDetail.as_view(), name='book-detail'),
]
설명:
/books/
: 책 목록 조회 및 새 책 생성./books/<pk>/
: 특정 책 조회, 업데이트, 삭제.
추가 팁
권한 및 인증 설정:
APIView
는 권한 및 인증을 쉽게 설정할 수 있습니다. 예를 들어, 인증된 사용자만 접근하도록 설정할 수 있습니다.from rest_framework.permissions import IsAuthenticated class BookList(APIView): permission_classes = [IsAuthenticated] def get(self, request, format=None): # ...
예외 처리:
get_object
메서드를 활용하여 객체를 가져오고, 존재하지 않을 경우 적절히 처리하는 것이 좋습니다.응답 상태 코드:
HTTP 상태 코드를 적절히 설정하여 클라이언트에게 정확한 정보를 전달합니다. 예를 들어, 성공 시 200 OK, 생성 시 201 Created, 삭제 시 204 No Content 등을 사용합니다.Serializer 유효성 검사:
데이터를 저장하거나 업데이트하기 전에 반드시 유효성을 검사하여 데이터의 무결성을 유지합니다.
요약
APIView
는 DRF에서 HTTP 메서드를 처리하기 위해def
키워드를 사용하여 메서드를 정의하는 클래스 기반 뷰입니다.- 주요 메서드로는
get
,post
,put
,patch
,delete
가 있으며, 각 메서드는 해당 HTTP 요청을 처리합니다. APIView
를 사용하면 RESTful API의 CRUD(Create, Read, Update, Delete) 작업을 쉽게 구현할 수 있습니다.- 직렬화기(Serializer)를 활용하여 데이터의 직렬화 및 역직렬화를 관리합니다.
- 권한 및 인증, 예외 처리, 상태 코드 관리 등 다양한 기능을 통해 견고한 API를 구축할 수 있습니다.
APIView
는 유연성과 강력한 기능을 제공하지만, 경우에 따라 DRF에서 제공하는 제네릭 뷰(Generic Views)나 뷰셋(ViewSets)을 사용하는 것이 더 간편할 수 있습니다. 프로젝트의 요구사항에 따라 적절한 뷰를 선택하여 사용
'django > Views' 카테고리의 다른 글
if serializer.is_valid() :user = serializer.save() user.email = user.customer_email에서 save()전에 user.email = user.customer_email을 먼저 할려면 (1) | 2024.11.18 |
---|---|
href="{% url ' ' %}">Home</a> (0) | 2024.11.01 |
pivot_table aggfunc 예제 (0) | 2024.10.24 |
template_name = 을 지정하지 않으면 어떤이름으로 템플렛이 만들어지는가 (0) | 2024.10.24 |
ListView의 전체 실행 순서 (1) | 2024.10.24 |