[django] DRF (Django Rest Framework) 으로 CRUD 구현하기

호이·2025년 1월 10일

django

목록 보기
2/2

django 프로젝트 시작하기 에서 django 프로젝트 생성 방법을 참조해주세요

1. 시작하기

DRF(Django Rest Framework)를 사용하면 djangoRest Api 개발이 가능하다. 파이썬으로 서버를 개발하는 것은 선호되지 않는 방법이다. 그 이유는 파이썬 언어는 오래 걸리는 작업을 수행 중일 때 다음 요청을 받아서 처리하지 못하고 서버가 프리징 상태에 있기 때문이다. 자바처럼 멀티 스레드를 지원하거나 node.js 처럼 non-blocking I/O를 지원하지 않으면 오래 걸리는 요청에 대해 대응을 하지 못한다. 그럼에도 불구하고 django를 사용하는 이유가 있다면 다음과 같이 이유를 꼽을 수 있겠다.

    1. 기본으로 지원하는 django 어드민 사용가능
    1. 파이썬 언어를 사용하기 때문에 빅데이터 분야 및 AI 연동가능
    1. ORM 기반으로 SQL Injection 방어
    1. django 에서 기본적으로 지원해주는 로그인 및 보안 기능 사용가능

2. 개발 환경 구축하기

DRF(Django Rest Framework)를 사용하기 위해서는 pip로 해당 패키지 설치가 필요하다. 다음의 명령어로 설치가 가능하다.

pip install djangorestframework

3. 개발하기

1. 모델 생성

API 통신을 통해 어떤 데이터 형태를 주고 받을지 정의가 필요하다. 즉, model생성이 필요하다.
다음과 같이 코드를 작성하여 데이터베이스에 username, email, password, created_at 컬럼을 생성한다

# Models.py
from django.db import models

# Create your models here.

# 위 코드에서 User 모델은 username, email, password, created_at 필드를 가지고 있습니다.
# __str__ 메서드는 User 객체를 출력할 때 사용됩니다.
class User(models.Model):
    username = models.CharField(max_length=50)
    email = models.EmailField()
    password = models.CharField(max_length=50)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.username

2. Serializer 생성

API 통신이 완료되면 객체를 JSON 형태로 반환하기 위해 직렬화를 거쳐야 한다. 앱이름 폴더안에 serializers.py라는 파일을 생성한다. 파일이 생성되면 다음과 같이 코드르 작성한다.

직렬화란?

    1. 주로 데이터 변환과 API 응답에서 사용된다.
    1. Python 객체(QuerySet, 모델 인스턴스 등)를 JSON, XML, YAML 같은 포맷으로 변환한다.
    1. 클라이언트로 데이터를 전송하거나 데이터를 저장할 때 사용한다.
    1. 주로 REST API를 구축할 때 필수적으로 사용됩니다.
# serializer.py
from rest_framework import serializers
from .models import User

# 위 코드에서 UserSerializer 클래스는 User 모델에 대한 시리얼라이저입니다.
# Meta 클래스의 model 속성은 시리얼라이저가 사용할 모델을 지정합니다.
# fields 속성은 JSON으로 직렬화할 필드 목록을 지정합니다.
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password', 'created_at')

3. API 생성

전제 조회 및 데이터 등록은 특정 데이터의 id값이 필요 없기 때문에 먼저 구현하였다.

# views.py
from django.http import JsonResponse
from rest_framework.views import APIView

from .models import User
from .serializers import UserSerializer

# 위 코드에서 UserListCreateView 클래스는 모든 사용자를 검색하고 새 사용자를 만들 수 있는 API를 정의합니다.
# UserRetrieveUpdateDestroyView 클래스는 특정 사용자를 검색, 수정, 삭제할 수 있는 API를 정의합니다.
class UserListView(APIView):

    # get 방식으로 users/ 에 접속할 경우 모든 유저를 보여주는 api를 생성합니다.
    # queryset은 db에서 모든 유저 정보를 가져오는 쿼리문을 자동으로 생성하고 실행하여 모든 유저 정보를 배열로 반환합니다.
    def get(self, request):
        queryset = User.objects.all()
        user_list = list()
        for user in queryset:
            user_list.append(UserSerializer(user).data)
        return JsonResponse(dict(status='ok', message='모든 유저', users=user_list))

    def post(self, request):
        username = request.data.get('username')
        email = request.data.get('email')
        password = request.data.get('password')

        # models.py에 작성된 User에 대한 필드값을 사용자가 입력한 정보로 설정하여 객체를 생성합니다.
        user = User.objects.create(username=username, email=email, password=password)
        # db에 저장합니다.
        user.save()
        return JsonResponse(dict(status='ok', message='회원가입에 성공하였습니다'))

특정 데이터 조회와 수정 및 삭제는 특정 데이터의 id값이 필요하고 한 클래스에서 Get, Post, Put, Delete의 함수를 각각 하나만 정의가 가능하기 때문에 별도의 클래스로 분리하였다.

# views.py
class UserDetailAPIView(APIView):

    def get(self, request, pk):
        user = User.objects.get(pk=pk)
        if user is not None:
            serializer = UserSerializer(user)
            user = serializer.data
            return JsonResponse(dict(status='ok', data=user))
        return JsonResponse(dict(status='error', message='요청을 찾을 수 없습니다.'))

    def put(self, request, pk):
        user = User.objects.get(pk=pk)
        if user is not None:
            serializer = UserSerializer(user, data=request.data)
            if serializer.is_valid():
                serializer.save()
                return JsonResponse(serializer.data)
            return JsonResponse(dict(status='error', message='잘못된 요청입니다.'))
        return JsonResponse(dict(status='error', message='요청을 찾을 수 없습니다.'))

    def delete(self, request, pk):
        user = User.objects.get(pk=pk)
        if user is not None:
            user.delete()
            return JsonResponse(dict(status='ok', message='삭제에 성공하였습니다.'))
        return JsonResponse(dict(status='error', message='요청을 찾을 수 없습니다.'))

4. URL 생성

백엔드 로직 생성이 끝났으니 로직을 실행할 엔드포인트를 생성하면 간단한 CRUD 장고 서버가 완성된다.

# urls.py
from django.contrib import admin
from django.urls import path

from testapi import views # 추가

urlpatterns = [
    path('admin/', admin.site.urls),
    path(r'users/', views.UserListView.as_view(), name='user-list'), # 추가
    path(r'users/<int:pk>/', views.UserDetailAPIView.as_view(), name='user-detail'), # 추가
]

5. 전체 코드

전체 프로젝트 파일을 github에 올려져 있다.
https://github.com/hsg5533/myapi

profile
기억하기 싫어서 기록하는 작은 공간

0개의 댓글