ACHO.pk devlog

[멋쟁이사자처럼11기] Django CRUD API 구현 본문

멋쟁이사자처럼

[멋쟁이사자처럼11기] Django CRUD API 구현

Acho 2023. 2. 2. 18:01

1. 모델 및 마이그레이션

본인프로젝트명/models.py 파일에 객체가 가지는 속성들을 지정할 수 있다. 

from django.db import models

class Product(models.Model):
    product_name = models.CharField(max_length=30, blank=False, default='')
    price = models.DecimalField(max_digits=20, decimal_places=1, blank=False, default=0)

Product라는 상품이 가지는 속성에 대해 정의를 할 수 있다.

설계한 내용을 마이그레이션을 통해 Django에게 전달하는 과정을 거쳐야한다.

python manage.py makemigrations products

products라는 app에 대해서  model 객체를 생성하고 있으므로 makemigrations 뒤에 app 이름을 명시하면 된다.

 

 

※ 주의

마이그레이션이 되지 않고 계속 오류가 떴다. 

ModuleNotFoundError: No module named 'corsheaders'

Python 버전을 확인하고 올바른 Python 버전을 사용하여 패키지를 재설치해봤더니 다행히 마이그레이션 성공!

 

예를 들어, 내 파이썬 버전은 3.8.3이므로 pip3.8이 설치된 django-cors-headers 패키지를 설치하면 된다.

 

참고로 이전에 나는

pipenv install django-cors-headers

로 패키지를 설치했었다.

 

 

마이그레이션에 성공하고 나면  앱 폴더 하위에 migrations 폴더가 생성이 된다.

DB에 객체 Product 명세가 나온다. 이 명세를 기준으로 데이터베이스를 구성하게 된다. id는 자동으로 만들어진다. 이 id는 각각의 product 데이터를 유일하게 구분할 수 있는 key 값으로 겹치지 않도록 설정이 된다.

# Generated by Django 4.0.4 on 2023-02-04 12:30

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Product',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('product_name', models.CharField(default='', max_length=30)),
                ('price', models.DecimalField(decimal_places=1, default=0, max_digits=20)),
            ],
        ),
    ]

 

migration은 migrate 준비할 파일이 만들어진 것으로 

python manage.py migrate products

migrate를 함으로써 products 설계도가 DB에 반영이 된다.

 

 

 

2. Serializer 생성

python에서 다뤄지는 객체를 HTTP 통신에서 api로 활용할 수 있는 JSON 형식으로 반환해주는 것이다.

products(프로젝트명)라고 하는 폴더 안에 serializer.py 파일을 생성해준다.

python 객체를 가져다가 JSON 형태로 변환해서 DB에 입력할 수 있는 형태로 변환해준다.

 

① 설치한 rest_framework에서 기능을 로드해야하기 때문에 serializers을 import 해온다.

② products 하위 models에서 설정했던 클래스도 가져오면 된다.

 

JSON 형식으로 Python 객체를 변환하는 소스를 만들어보자!!

from rest_framework import serializers
from products.models import Product

class ProductSerializer(serializers.ModelSerializer): # serializers에 있는 ModelSerializer를 상속받아 구현
    
    class Meta:  # Meta 클래스를 열어준다.
        model = Product
        fields = (
            'id',
            'product_name',
            'price'
        )

 

어떤 model를 JSON 형태로 변환할지 직렬화할지 결정해야한다. Product 클래스를 model로 삼아서 변환을 할거기 때문에 model = Product를 해준다.

fields에는 어떤 항목에 대해서 JSON 형태로 변환할건지 적어야한다. 이 데이터는 migrations 폴더 하위 파일에서 fields에서 확인할 수 있다. 

 

마지막으로 migrate를 해주면 된다.

 

 

 

 

3. View, Url 설정 및 CRUD 구현

클라이언트의 요청을 서버가 응답을 해주기 위해서는 views.py에 viewset을 정의해줘야한다.

viewset이란 Django RestFramework에 내장되어 있는 모듈 중 하나로 모든 함수나 클래스를 만들 필요없이 CRUD의 모든 기능을 상속을 받아 사용할 수 있다.

 

3-1. API Views 만들기

views.py에 클래스 생성

ProductViewSet이라는 Class에서 ModelViewSet를 상속받아 ModelViewSet의 모든 기능을 활용할 수 있게한다.

중요

어떤 Model에 대해서 다룰지 정하는 queryset과 serializer_class에는 이전에 만든  ProductSerializer를 넣어주면 된다.

from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet

from .models import Product
from .serializer import ProductSerializer

class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

 

 

3-2. 앱/urls 파일에 url 라우팅

products(앱 명) 폴더 하위에 urls.py를 만들어준다.

DRF의 대표 클래스 중 하나인 Router는 자동으로 url 라우팅을 해준다. DRF에는 SimpleRouter와 DefaultRouter를 제공하며 어떤 경로로 요청하고 응답을 받을지 정해준다.

'product' 와 ProductViewSet 을 연결해서 실제 경로를 통해 API 요청을 주고받을 수 있다.

from django.contrib import admin
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from . import views
from products.views import ProductViewSet

router = DefaultRouter()   
router.register('product', views.ProductViewSet) 

urlpatterns = [
    path('', include(router.urls))
]

 

 

3-3. 최상위 urls 파일에 url 등록

myproj(프로젝트 명) 폴더 하위인 최상위 urls.py에 우리가 커스텀한 url를 등록해줘야한다.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('products.urls')),
]

 

 

결과

 

 

4. API 테스트 (분할 2)

DRF를 사용해서 구축을 했을 때, GET/POST/PUT/DELETE의 HTTP 메소드를 각각 어떤 경로를 받아 처리할지 정하지 않아도 DefaultRouter를 통해 모두 세팅할 수 있다. API를 손쉽게 구성할 수 있다는 측면에서 의의가 있다.

 

 

4-1. 데이터 조회 (GET)

Postman이라는 API tester를 사용해서 프론트 페이지가 만들어지지 않았을 때, 백엔드로 정상 작동을 확인할 수 있는 방법이다.

백엔드 서버를 돌리고 주소창에 우리의 서버 주소를 입력한 후 GET를 선택하여 우리가 원하는 데이터가 출력되는 걸 확인할 수 있다.

 

 

4-2. 데이터 생성 (POST)

데이터를 생성할 때에는 POST로 설정하고, Body에 필요한 정보를 넣어 send 버튼으로 데이터의 응답이나 오류 메시지를 확인할 수 있다.

에러

{
    "detail": "Unsupported media type \"text/plain\" in request."
}

입력 형식을 JSON 타입으로 바꿔주면 에러가 해결이 된다. id는 자동으로 생성되는 값이기 때문에 우리가 따로 설정하지 않아도 된다.

 

 

4-3. 데이터 수정 (PUT)

새로운 new Request를 추가로 생성해준다. 주소창에 변경하고자 하는 데이터의 id 값을 넣어줘야한다.

우리의 백엔드 서버에서 raw data를 복사해서 그대로 붙여넣기한다.

 

상품 keyboard의 가격을 수정해서 put할 수 있다.

 

 

 

결과

 

Comments