Post

Django: DRF with Relationship

Django REST Framework를 활용한 관계형 데이터 직렬화 및 API 구현 가이드.

Django: DRF with Relationship

Django REST Framework(DRF)를 사용하여 관계형 데이터를 직렬화하고 제공하는 방법에 대한 내용을 다룹니다.

1. Comment 모델 작성

우선, articles 앱에 댓글(Comment) 모델을 작성하고 데이터베이스에 반영해야 합니다.

1
2
3
4
5
6
7
8
9
10
# articles/models.py
from django.db import models

class Comment(models.Model):
    article = models.ForeignKey(
        'Article', on_delete=models.CASCADE, related_name="comments"
    )
    content = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

주요 포인트

  • ForeignKey 관계: CommentArticle과 1:N 관계를 가집니다.
  • related_name: 역참조를 쉽게 하기 위해 comments라는 이름을 설정했습니다.

Migrate

모델을 작성한 후, 데이터베이스에 반영합니다.

1
2
python manage.py makemigrations
python manage.py migrate

2. Serializer 작성

Comment 모델을 직렬화하는 Serializer를 작성합니다.

1
2
3
4
5
6
7
8
# articles/serializers.py
from rest_framework import serializers
from .models import Comment

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = "__all__"

주요 포인트

  • fields = "__all__": 모델의 모든 필드를 포함합니다.

3. Seeding 데이터 생성

Django Seed를 사용하여 articles 앱에 20개의 랜덤 데이터를 생성합니다.

1
python manage.py seed articles --number=20

특정 모델에 데이터를 추가하려면 아래 명령어를 사용합니다.

1
python manage.py seed articles --number=20 --seeder "Comment.article_id" 2

주요 포인트

  • --seeder: 특정 필드에 값을 설정할 수 있습니다.

4. 특정 Article의 댓글 조회 API 작성

특정 Article에 대한 모든 댓글을 조회하는 API를 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
# articles/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from .models import Article
from .serializers import CommentSerializer

class CommentListAPIView(APIView):
    def get(self, request, pk):
        article = get_object_or_404(Article, pk=pk)
        comments = article.comments.all()
        serializer = CommentSerializer(comments, many=True)
        return Response(serializer.data)

URL 설정

1
2
3
4
5
6
7
# articles/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("<int:pk>/comments/", views.CommentListAPIView.as_view(), name="comment_list"),
]

5. 새로운 댓글 작성

API 작성

1
2
3
4
5
6
7
8
9
10
11
# articles/views.py
from rest_framework import status

class CommentListAPIView(APIView):
    ...
    def post(self, request, pk):
        article = get_object_or_404(Article, pk=pk)
        serializer = CommentSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            serializer.save(article=article)
            return Response(serializer.data, status=status.HTTP_201_CREATED)

Serializer 수정

1
2
3
4
5
6
# articles/serializers.py
class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = "__all__"
        read_only_fields = ("article",)

주요 포인트

  • read_only_fields: article 필드를 읽기 전용으로 설정하여 데이터 생성 시 제외합니다.

6. 댓글 삭제

API 작성

1
2
3
4
5
6
7
8
9
10
# articles/views.py
class CommentDetailAPIView(APIView):
    def get_object(self, comment_pk):
        return get_object_or_404(Comment, pk=comment_pk)

    def delete(self, request, comment_pk):
        comment = self.get_object(comment_pk)
        comment.delete()
        data = {"pk": f"{comment_pk} is deleted."}
        return Response(data, status=status.HTTP_200_OK)

URL 설정

1
2
3
4
# articles/urls.py
urlpatterns += [
    path("comments/<int:comment_pk>/", views.CommentDetailAPIView.as_view(), name="comment_detail"),
]

7. 댓글 수정

API 작성

1
2
3
4
5
6
7
8
9
# articles/views.py
class CommentDetailAPIView(APIView):
    ...
    def put(self, request, comment_pk):
        comment = self.get_object(comment_pk)
        serializer = CommentSerializer(comment, data=request.data, partial=True)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data)
This post is licensed under CC BY 4.0 by the author.