AI웹 개발자 과정 공부 (팀스파르타)/프로젝트
24.05.09_TIL ( 팀 프로젝트 : 스파르타 뉴스 Django ) _ 3. 대댓글 구현 & 오류수정
티아(tia)
2024. 5. 9. 12:43
728x90
[ 두번째 프로젝트 ]
스파르타 뉴스를 만들어 보자.
++ 팀 스로젝트로 팀과의 협업이 중요하다.
++ 장고 공식 문서는 항상 확인하기
https://docs.djangoproject.com/en/4.2/
https://github.com/1489ehdghks/spartaNews
1. 대댓글 구현해보자.
- articles 에서 urls.py 추가해주기
path( # 대댓글 조회하기
"comments/<int:comment_id>/reply/",
views.CommentReplyAPIView.as_view(),
name="comment_reply"
),
path( # 대댓글 삭제하기
"comments/<int:parent_comment_id>/replies/<int:reply_id>/",
views.CommentReplyDetailAPIView.as_view(),
name="comment_reply_detail"
),
- articles 에서 models.py 에 대댓글을 상속받을 부모댓글 추가하기
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="comments")
content = models.TextField()
# 작성자 필드 추가
user_id = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
parent_comment = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='replies')
class Meta:
db_table = 'comments'
- articles 의serializers.py 수정하기
from rest_framework import serializers
from .models import Article, Comment, ArticleLike
class ReplySerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = "__all__"
class CommentSerializer(serializers.ModelSerializer):
# 대댓글 표시
replies = ReplySerializer(many=True, read_only=True)
class Meta:
model = Comment
fields = "__all__"
read_only_fields = ("article",)
# 댓글에 article 표시 없앰
def to_representation(self, instance):
ret = super().to_representation(instance)
ret.pop("article")
return ret
class ArticleSerializer(serializers.ModelSerializer) :
class Meta :
model = Article
fields = '__all__'
class ArticleDetailSerializer(ArticleSerializer):
like_count = serializers.IntegerField(read_only = True)
# 댓글 수 표시
comments_count = serializers.IntegerField(source="comments.count", read_only=True)
comments = CommentSerializer(many = True, read_only = True)
# 대댓글 표시
replies = ReplySerializer(many=True, read_only=True)
class ArticleLikeSerializer(serializers.ModelSerializer) :
class Meta :
model = ArticleLike
fields = "__all__"
def to_representation(self, instance):
representation = super().to_representation(instance)
representation['like_count'] = instance.like_count.count()
return representation
- articles 의 view.py 추가해주기
from .serializers import ArticleDetailSerializer, ArticleSerializer, CommentSerializer, ReplySerializer
...
class CommentReplyAPIView(APIView):
# 대댓글 조회하기
def get(self, request, parent_comment_id, reply_id):
parent_comment = get_object_or_404(Comment, pk=parent_comment_id)
reply = get_object_or_404(parent_comment.replies.all(), pk=reply_id)
serializer = CommentSerializer(reply)
return Response(serializer.data)
# 대댓글 생성하기
def post(self, request, parent_comment_id):
parent_comment = get_object_or_404(Comment, pk=parent_comment_id)
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(article=parent_comment.article, parent_comment=parent_comment)
return Response(serializer.data, status=status.HTTP_201_CREATED)
class CommentReplyDetailAPIView(APIView):
# 대댓글 삭제하기
def delete(self, request, parent_comment_id, reply_id):
parent_comment = get_object_or_404(Comment, pk=parent_comment_id)
reply = get_object_or_404(parent_comment.replies.all(), pk=reply_id)
reply.delete()
return Response(status=status.HTTP_200_OK)
# 대댓글 수정하기
def put(self, request, parent_comment_id, reply_id):
parent_comment = get_object_or_404(Comment, pk=parent_comment_id)
reply = get_object_or_404(parent_comment.replies.all(), pk=reply_id)
serializer = CommentSerializer(reply, data=request.data, partial=True)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
2. 포스트맨으로 확인작업
- 슈퍼아이디를 만들어서 테스트 해보자.
-
python manage.py createsuperuser
- 데이터 생성하기 먼저 seed를 쓸 수 있게 장고파일을 깔아주자.
pip install django-seed
그 다름으로 freeze 해준다.
pip freese > reqirements.txt
- seeding 해보자.
python manage.py seed articles --number=30
- django seed를 특정 article 에 댓글을 20개 생성해보자.
python manage.py seed articles --number=20 --seeder "Comment.article_id" 2
3. 포스트맨으로 확인작업 후 코드 수정
- articles 의 models.py 에서 Article가 맨 위로 와야해서 순서 변경
from django.db import models
from django.conf import settings
class Article(models.Model) :
title = models.CharField(max_length=50)
content = models.TextField()
url = models.URLField()
create_at = models.DateTimeField(auto_now_add=False)
updated_at = models.DateTimeField(auto_now=False)
user_id = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name = 'articles')
class ArticleLike(models.Model) :
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="article_likes")
user_id = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="user_likes")
like_count =models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name = 'likes',
default=0
)
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="comments")
content = models.TextField()
# 작성자 필드 추가
user_id = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
parent_comment = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='replies')
class Meta:
db_table = 'comments'
- articles 의 serializers.py 에서 Reply와 Comment 부분 수정
from rest_framework import serializers
from .models import Article, Comment, ArticleLike
class ReplySerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = "__all__"
read_only_fields = ("article",)
class CommentSerializer(serializers.ModelSerializer):
# 대댓글 표시
replies = ReplySerializer(many=True, read_only=True)
class Meta:
model = Comment
fields = "__all__"
read_only_fields = ("article",)
# 댓글에 article 표시 없앰
def to_representation(self, instance):
ret = super().to_representation(instance)
ret.pop("article")
return ret
class ArticleSerializer(serializers.ModelSerializer) :
class Meta :
model = Article
fields = '__all__'
class ArticleDetailSerializer(ArticleSerializer):
like_count = serializers.IntegerField(read_only = True)
# 댓글 수 표시
comments_count = serializers.IntegerField(source="comments.count", read_only=True)
comments = CommentSerializer(many = True, read_only = True)
# 대댓글 표시
replies = ReplySerializer(many=True, read_only=True)
class ArticleLikeSerializer(serializers.ModelSerializer) :
class Meta :
model = ArticleLike
fields = "__all__"
def to_representation(self, instance):
representation = super().to_representation(instance)
representation['like_count'] = instance.like_count.count()
return representation
- urls.py 는 생성하는 부분만 따로 주고 조회, 수정, 삭제하는 부분 path를 나누어줌
path( # 대댓글 생성하기
"comments/<int:comment_id>/reply/",
views.CommentReplyAPIView.as_view(),
name="comment_reply"
),
path( # 대댓글 조회, 수정, 삭제하기
"comments/<int:parent_comment_id>/replies/<int:reply_id>/",
views.CommentReplyDetailAPIView.as_view(),
name="comment_reply_detail"
),
- views.py는 대댓글은 조회, 생성, 수정, 삭제가 다 안되서 바꾸어주었다.
class CommentListAPIView(APIView):
# 댓글 조회하기
def get(self, request, article_id):
article = get_object_or_404(Article, pk=article_id)
comments = article.comments.all()
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
# 댓글 생성하기
def post(self, request, article_id):
article = get_object_or_404(Article, pk=article_id)
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)
class CommentDetailAPIView(APIView):
# 댓글 삭제하기
def delete(self, request, comment_id):
comment = get_object_or_404(Comment, pk=comment_id)
comment.delete()
data = {"id": f"{comment_id} is deleted."}
return Response(data, status=status.HTTP_200_OK)
# 댓글 수정하기
def put(self, request, comment_id):
comment = get_object_or_404(Comment, pk=comment_id)
serializer = CommentSerializer(comment, data=request.data, partial=True)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
class CommentReplyAPIView(APIView):
# 대댓글 생성하기
def post(self, request, comment_id):
parent_comment = get_object_or_404(Comment, pk=comment_id)
serializer = ReplySerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(article=parent_comment.article, parent_comment=parent_comment)
return Response(serializer.data, status=status.HTTP_201_CREATED)
class CommentReplyDetailAPIView(APIView):
# 대댓글 조회하기
def get(self, request, parent_comment_id, reply_id):
parent_comment = get_object_or_404(Comment, pk=parent_comment_id)
reply = get_object_or_404(parent_comment.replies.all(), pk=reply_id)
serializer = ReplySerializer(reply)
return Response(serializer.data)
# 대댓글 삭제하기
def delete(self, request, parent_comment_id, reply_id):
parent_comment = get_object_or_404(Comment, pk=parent_comment_id)
reply = get_object_or_404(parent_comment.replies.all(), pk=reply_id)
reply.delete()
return Response(status=status.HTTP_200_OK)
# 대댓글 수정하기
def put(self, request, parent_comment_id, reply_id):
parent_comment = get_object_or_404(Comment, pk=parent_comment_id)
reply = get_object_or_404(parent_comment.replies.all(), pk=reply_id)
serializer = ReplySerializer(reply, data=request.data, partial=True)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
4. 참고 블로그
https://yesjiwon5304.tistory.com/33
https://devvvyang.tistory.com/48
반응형