📘 DRF
DRF with Relationship
Relationship이 있는 데이터를 직렬화(Serialization)하여 제공하는 방법을 학습해 보자
댓글 생성을 위한 사전 작업
1. Comment 모델을 작성
더보기
class Comment(models.Model):
# 1. 외래 키로, 댓글이 어느 글(Article)에 속하는지 알려줌
# 2. Article 모델과 Comment 모델이 1:N의 관계를 가짐
# 3. on_delete=models.CASCADE -> Article이 삭제되면, 댓글도 함께 삭제
article = models.ForeignKey(Article, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True) # 댓글이 처음 생성됐을 때의 시간 기록
updated_at = models.DateTimeField(auto_now=True) # 댓글이 수정될 때마다 시간 기록
2. Migrate
더보기
python manage.py makemigrations
python manage.py migrate
3. CommentSerializer 작성
더보기
from .models import Comment
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = "__all__"
4. 🌱 20개의 랜덤 한 데이터를 생성 (seed)
더보기
python manage.py seed articles --number=20
먼저 생각해보기 🤔
어떤 API가 필요할까?
Name | Method | Endpoint |
특정 Article의 댓글 조회 | GET | /articles/<int:pk>/comments/ |
새로운 댓글 작성 | POST | /articles/<int:pk>/comments/ |
댓글 수정 | PUT | /articles/comments/<int:comment_pk>/ |
댓글 삭제 | DELETE | /articles/comments/<int:comment_pk>/ |
1. 특정 Article의 댓글 조회
1.1. articles/urls.py
더보기
# 특정 Article의 댓글 조회
path("<int:article_pk>/comments/",
views.CommentListAPIView.as_view(),
name="comment_list"),
1.2. articles/models.py
더보기
⬇️
class Comment(models.Model):
# 1. 외래 키로, 댓글이 어느 글(Article)에 속하는지 알려줌
# 2. Article 모델과 Comment 모델이 1:N의 관계를 가짐
# 3. on_delete=models.CASCADE -> Article이 삭제되면, 댓글도 함께 삭제
article = models.ForeignKey(
Article, on_delete=models.CASCADE, related_name="comments") # 매니저 이름 "comments"로 해주기
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True) # 댓글이 처음 생성됐을 때의 시간 기록
updated_at = models.DateTimeField(auto_now=True) # 댓글이 수정될 때마다 시간 기록
매니저 이름이 생겼어요!
article = models.ForeignKey(
Article, on_delete=models.CASCADE, related_name="comments") # 매니저 이름 "comments"로 해주기
migrations과 migrate 해주세요!
1.3. articles/views.py
더보기
from .serializers import CommentSerializer
class CommentListAPIView(APIView):
def get(self, request, article_pk):
# Article 모델에서 찾아와요. 근데 Article 모델에는 comment가 없잖아요?(역참조) ⬇️
article = get_object_or_404(Article, pk=article_pk)
# 그래서 Comment 모델의 매니저인 "comments"를 데리고 와서, 해당 글에 있는 comments들을 데려와요 ⬇️
comments = article.comments.all() # 조회된 comments들을
serializer = CommentSerializer(comments, many=True) # serializer에 넣어줬어요. 많으니까 many=True
return Response(serializer.data)
1.4.🌱 특정 모델에 데이터 넣기 (seed)
더보기
python manage.py seed articles --number=20 --seeder "Comment.article_id" 1
1번 Article에 20개의 댓글을 생성했어요
1.5. postman
2. 새로운 댓글 작성
2.1. articles/views.py/CommentListAPIView
더보기
class CommentListAPIView(APIView):
def post(self, request, article_pk):
article = get_object_or_404(Article, pk=article_pk) # 역참조
serializer = CommentSerializer(data=request.data) # data에 POST 받은 값을 넣어줘요, 여기엔 content 값만 있어요
if serializer.is_valid(raise_exception=True): # 값이 유효하다면, 예외 발생 True
serializer.save(article=article) # 저장할 때, 필요한 나머지 데이터를 article로 채워줌
return Response(serializer.data, status=status.HTTP_201_CREATED)
2.2. articles/serializer.py/CommentSerializer
- read_only_fields
- serializer.is_valid 를 통과하지 못 한다.
- 이럴 때는 read_only_fields 를 설정해서 특정 필드를 직렬화 로직에 포함하지 않고, 반환 값에만 포함하도록 할 수 있다.
- → serializer 입장에서는 내가 넘겨받은 데이터에 article 정보가 없기 때문!
더보기
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = "__all__"
read_only_fields = ("article",)
2.3. postman
3. 댓글 삭제
3.1. articles/urls.py
더보기
# comment 삭제하기
path("comments/<int:comment_pk>/",
views.CommentDetailAPIView.as_view(),
name="comment_detail"),
3.2. articles/views.py
더보기
class CommentDetailAPIView(APIView):
# 댓글 삭제하기
def delete(self, request, comment_pk):
comment = get_object_or_404(Comment, pk=comment_pk) # Comment 모델을 통해서 comment 들고 와요
comment.delete() # 가져온 comment를 삭제해주고,
return Response(status=status.HTTP_204_NO_CONTENT) # 204를 보여주면 삭제 끝
3.3. postman
더보기
삭제 됐다!
댓글을 조회해 봤더니 41번 댓글이 없어졌다!
4. 댓글 수정
4.1. articles/views.py
더보기
class CommentDetailAPIView(APIView):
# 댓글 수정하기
def put(self, request, comment_pk):
comment = get_object_or_404(Comment, pk=comment_pk)
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
4.2. postman
4.1. articles/views.py ➡️ 좀 더 편리한 코드
더보기
⬇️
class CommentDetailAPIView(APIView):
# 공통된 get_object를 수정하기 편하게끔 함수 만들어주기
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 모델을 통해서 comment 들고 와요
comment.delete() # 가져온 comment를 삭제해주고,
return Response(status=status.HTTP_204_NO_CONTENT) # 204를 보여주면 삭제 끝
# 댓글 수정하기
def put(self, request, comment_pk):
comment = self.get_object(comment_pk)
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
- get_object_or_404(Comment, pk=comment_pk) ➡️ self.get_object(comment_pk)
- def get_object 추가
# 공통된 get_object를 수정하기 편하게끔 함수 만들어주기
def get_object(self, comment_pk):
return get_object_or_404(Comment, pk=comment_pk)
이 코드를 추가했어요!
Postman 정리하기
더보기
Add folder를 눌러주세요
생성해 주신 폴더에 API들 넣어주세요
끝!
'공부 > DRF 공부' 카테고리의 다른 글
[DRF] Token Auth with JWT, 접근 제한 및 접근하기 (0) | 2025.02.02 |
---|---|
[DRF] Serializer 활용하기 (1) | 2025.01.31 |
[DRF] DRF CBV(Class Based View) 사용하기 (0) | 2025.01.30 |
[DRF] DRF Single Model CRUD (0) | 2025.01.30 |
[DRF] Django REST Framework 시작하기, Postman (0) | 2025.01.28 |