티스토리 뷰

728x90

 

 

[ 두번째 프로젝트 ] 

 

 

스파르타 뉴스를 만들어 보자.

 

 

 

 

++  팀 스로젝트로 팀과의 협업이 중요하다.

++  장고 공식 문서는 항상 확인하기 

https://docs.djangoproject.com/en/4.2/

 

 

https://github.com/1489ehdghks/spartaNews

 

GitHub - 1489ehdghks/spartaNews

Contribute to 1489ehdghks/spartaNews development by creating an account on GitHub.

github.com

 

 

 

 

 

 

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

 

[Django] 댓글, 대댓글, 페이지네이션 구현하기

제가 [원티드 X 위코드] 프리온보딩 코스에 참여하면서, 댓글 대댓글 , 페이지네이션 기능을 구현해볼 기회가 생겼어요. 기능 구현하면서 배웠던 부분들을 정리해보려고 합니다! 시작할게요 :)

yesjiwon5304.tistory.com

 

https://devvvyang.tistory.com/48

 

[Django] 인스타그램 클론 코딩(7) - 대댓글 기능 구현

[이전 글] [Django] 인스타그램 클론 코딩(6) - 팔로우(follow) 기능 구현 [Django] 인스타그램 클론 코딩(6) - 팔로우(follow) 기능 구현 [이전 글] [Django] 인스타그램 클론 코딩(5) - 좋아요(Like) 기능 구현 [Dja

devvvyang.tistory.com

 

https://velog.io/@fall031/TIL-40.-Django-%EB%8C%93%EA%B8%80%EB%8C%80%EB%8C%93%EA%B8%80-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0

 

TIL 40. Django 댓글/대댓글 구현하기

Django를 이용하여 게시판의 댓글/대댓글 구현을 하였습니다.먼저 아래과 같이 모델링을 하였습니다.대댓글도 결국 댓글이므로 자기 class를 참조하여 parent_comment가 없을 경우 댓글이고, 있을 경우

velog.io

 

https://velog.io/@rlagurwns112/django-%EB%8C%80%EB%8C%93%EA%B8%80-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0

 

django 대댓글 구현하기

기본적으로 대댓글은 comment모델과 외래키로 연결해서 구현한다. comment모델 자체에 스스로 외래키를 걸거나 대댓글 모델을 새로 만드는 방법이 있는데 후자의 방법으로 구현했다. 아티클에 외래

velog.io

 

 

 

 

 

반응형
반응형
TAG
more
최근에 올라온 글