오늘은 먼저 상품 관련 기능의 CRUD를 구현해보려고 한다.
CRUD의 구현 조건은 다음과 같다.
- 상품 등록
- Endpoint: /api/products
- Method: POST
- 조건: 로그인 상태, 제목과 내용, 상품 이미지 입력 필요.
- 구현: 새 게시글 생성 및 데이터베이스 저장.
- 상품 목록 조회
- Endpoint: /api/products
- Method: GET
- 조건: 로그인 상태 불필요.
- 구현: 모든 상품 목록 페이지네이션으로 반환.
- 상품 수정
- Endpoint: /api/products/<int:productId>
- Method: PUT
- 조건: 로그인 상태, 수정 권한 있는 사용자(게시글 작성자)만 가능.
- 검증: 요청자가 게시글의 작성자와 일치하는지 확인.
- 구현: 입력된 정보로 기존 상품 정보를 업데이트.
- 상품 삭제
- Endpoint: /api/products/<int:productId>
- Method: DELETE
- 조건: 로그인 상태, 삭제 권한 있는 사용자(게시글 작성자)만 가능.
- 검증: 요청자가 게시글의 작성자와 일치하는지 확인.
- 구현: 해당 상품을 데이터베이스에서 삭제.
아직 회원기능을 만들지 않았으므로 로그인상태나 권한을 확인하는게 아닌 기본적인 기능만을 구현해야겠다.
먼저 상품 등록의 조건을 보면서 필요한 필드를 가진 모델을 만든다.
from django.db import models
from django.conf import settings
class Product(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
image = models.ImageField(upload_to="images/")
seller = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.title
필수적으로 입력해야 하는 부분은 제목, 내용, 상품 이미지 부분이기 때문에
나머지는 자동으로 처리할 수 있는 로직을 구현해야 한다.
seller는 우선 구현만 한 다음에 나중에 로그인을 한 사용자의 키를 받게 할 생각이다.
이미지 파일을 등록하기 위해서 settings.py와 urls.py에 미디어 파일 설정을 추가해주고
products 앱의 urls.py로 가서 경로를 설정해 준다.
from django.urls import path
from . import views
urlpatterns = [
path("", views.ProductListAPIView.as_view()),
]
이번 프로젝트는 클래스형 view를 사용하려고 노력할 것이며, 클래스형 view를 사용할 때 as_view()를 잊지말자.
이제 데이터를 처리할 view를 만들어줘야 하는데 쿼리셋이, 인스턴스를 전송이 가능하도록 json형태로 만들어줄
serializer(직렬화) 파일을 만든다.
# products/serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = "__all__"
이제 준비는 끝났고 같은 url에서 요청된 method에 따라서 데이터를 처리해주는 클래스형 view를 정의한다.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Product
from .serializers import ProductSerializer
class ProductListAPIView(APIView):
def get(self, request):
products = Product.objects.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
def post(self, request):
serializer = ProductSerializer(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)
이제 수정과 삭제를 만들어야하는데 product의 id값을 받아서 응답을 하고 있기 때문에
수정과 삭제와 같이 product의 id로 게시물을 볼 수 있는 상세 조회 기능도 같이 넣어줄 생각이다.
urlpatterns = [
path("", views.ProductListAPIView.as_view()),
path("<int:productId>/", views.ProductDetailAPIView.as_view()),
]
product id를 받아서 원하는 요청을 해야하니 ProductDetailAPIView를 정의해줘야 한다.
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Product
from .serializers import ProductSerializer
class ProductDetailAPIView(APIView):
def get_object(self, productId):
return get_object_or_404(Product, id=productId)
def get(self, request, productId):
product = self.get_object(productId)
serializer = ProductSerializer(product)
return Response(serializer.data)
def put(self, request, productId):
product = self.get_object(productId)
serializer = ProductSerializer(
product, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, productId):
product = self.get_object(productId)
product.delete()
data = f"{productId}번 게시물 삭제"
return Response(data)
먼저 get_object 함수를 정의하여 원하는 객체를 가지고 온다.
상세 조회는 아까 목록 조회와 비슷하게 구현을 했고,
수정에서 봐야 할 점은 partial속성을 주는 것이다. partial속성을 주면 부분 입력으로도 원하는 부분에 수정이 가능하다.
삭제는 원하는 객체를 가지고 와서 삭제를 해주는 것 밖에 없다.
'웹 개발' 카테고리의 다른 글
[Django] DRF Project - 4 (0) | 2024.09.09 |
---|---|
[Django] DRF Project - 3 (0) | 2024.09.05 |
[Django] DRF Project - 1 (0) | 2024.09.03 |
[Django] Token Auth with JWT (0) | 2024.08.30 |
[Django] 심화 과정에 들어가기 전 개념 (0) | 2024.08.29 |