이 내용은, 자바 + 스프링에 익숙한 개발자 시각으로 보는 DRF 입니다.
Django REST framework(DRF)는 Django 기반의 강력한 RESTful API 프레임워크입니다. DRF의 주요 구성 요소와 아키텍처는 다음과 같습니다:
ModelViewSet은 CRUD 작업을 자동으로 처리합니다.ModelSerializer를 사용하여 모델 기반 시리얼라이저를 쉽게 생성할 수 있습니다.DefaultRouter를 사용하여 URL을 자동으로 생성할 수 있습니다.DRF를 사용한 RESTful API 개발의 일반적인 순서는 다음과 같습니다:
Spring의 Model -> Repository -> Service -> Controller 순서와 유사.
Django의 모델은 데이터베이스 스키마를 정의하고, 데이터베이스 테이블과 매핑됩니다.
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.TextField(blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
쿼리셋은 데이터베이스에서 데이터를 가져오는 데 사용됩니다. 일반적으로 모델 매니저를 통해 정의합니다.
from django.db import models
class UserManager(models.Manager):
def active_users(self):
return self.filter(is_active=True)
class User(AbstractUser):
bio = models.TextField(blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
objects = UserManager()
시리얼라이저는 Django 모델 인스턴스를 JSON 등으로 직렬화하거나 역직렬화하는 데 사용됩니다.
Spring MVC에서는 Jackson ObjectMapper 등의 역할.
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name', 'bio', 'location', 'birth_date']
def validate_email(self, value):
if not value.endswith('@example.com'):
raise serializers.ValidationError("Email must be from example.com domain")
return value
뷰셋은 기본적인 CRUD 작업을 처리하는 뷰의 모음입니다. DRF의 ModelViewSet을 사용하여 기본 CRUD 작업을 쉽게 구현할 수 있습니다.
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
라우터는 URL 패턴과 뷰셋을 매핑합니다. DRF의 DefaultRouter를 사용하여 URL을 자동으로 생성할 수 있습니다.
아래 r'users'는 /users 경로를 라우터에 등록하겠다는 뜻.
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import UserViewSet
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = [
path('', include(router.urls)),
]
쿼리셋을 정의하여 데이터베이스에서 필터링된 데이터를 가져올 수 있습니다.
from django.db import models
class UserManager(models.Manager):
def active_users(self):
return self.filter(is_active=True)
class User(AbstractUser):
bio = models.TextField(blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
objects = UserManager()
@action 데코레이터를 사용하여 ViewSet에 커스텀 액션을 추가할 수 있습니다.
from rest_framework.decorators import action
from rest_framework.response import Response
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
@action(detail=True, methods=['post'], url_path='activate', url_name='activate')
def activate_user(self, request, pk=None):
user = self.get_object()
user.is_active = True
user.save()
return Response({'status': 'user activated'})
@action(detail=True, methods=['post'], url_path='deactivate', url_name='deactivate')
def deactivate_user(self, request, pk=None):
user = self.get_object()
user.is_active = False
user.save()
return Response({'status': 'user deactivated'})
비즈니스 로직을 서비스 계층으로 분리하여 코드의 재사용성과 유지보수성을 높일 수 있습니다.
# apps/users/services.py
from .models import User
class UserService:
@staticmethod
def activate_user(user):
user.is_active = True
user.save()
@staticmethod
def deactivate_user(user):
user.is_active = False
user.save()
# apps/users/views.py
from .services import UserService
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
@action(detail=True, methods=['post'], url_path='activate', url_name='activate')
def activate_user(self, request, pk=None):
user = self.get_object()
UserService.activate_user(user)
return Response({'status': 'user activated'})
@action(detail=True, methods=['post'], url_path='deactivate', url_name='deactivate')
def deactivate_user(self, request, pk=None):
user = self.get_object()
UserService.deactivate_user(user)
return Response({'status': 'user deactivated'})
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name', 'bio', 'location', 'birth_date']
def validate_email(self, value):
if not value.endswith('@example.com'):
raise serializers.ValidationError("Email must be from example.com domain")
return value
def create(self, validated_data):
return User.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.bio = validated_data.get('bio', instance.bio)
instance.location = validated_data.get('location', instance.location)
instance.birth_date = validated_data.get('birth_date', instance.birth_date)
instance.save()
return instance
serializer.is_valid()serializer = UserSerializer(data=request.data)serializer = UserSerializer(user, data=request.data, partial=True)serializer.save()# POST 요청에서 새로운 사용자 생성
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
else:
print(serializer.errors)
# PUT 또는 PATCH 요청에서 기존 사용자 업데이트
serializer = UserSerializer(user, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
else:
print(serializer.errors)
Serializer의 자동으로 호출되는 메서드 정의 및 사용.