Django | 인스타그램 클론 코딩(10) - 대댓글 달기

Sua·2021년 2월 13일
2

Django

목록 보기
16/23
post-thumbnail
post-custom-banner

🧑‍💻 대댓글 달기

지난 시간에는 게시물 및 댓글 삭제, 수정 기능을 구현하였습니다. 이번에는 대댓글 기능을 구현하도록 하겠습니다. 마찬가지로 로그인 데코레이터를 사용해서 로그인된 권한있는 유저만이 대댓글 기능을 사용할 수 있도록 하겠습니다.

🔎 대댓글 기능 분석

하나의 댓글에 대해 여러 개의 대댓글이 달릴 수 있습니다.(1:N)

🛠 App

대댓글 기능은 게시물과 관련되어 있으므로 posting 앱에서 작성합니다.

🖌 Model 작성

class Comment(models.Model):
    content        = models.CharField(max_length=500)
    created_at     = models.DateTimeField(auto_now_add=True)
    user           = models.ForeignKey('user.User', on_delete=models.CASCADE)
    posting        = models.ForeignKey('Posting', on_delete=models.CASCADE)
    parent_comment = models.ForeignKey('self', on_delete=models.CASCADE, null=True)  --> 추가

    class Meta:
        db_table = 'comments'

Q. 대댓글을 위한 테이블을 생성하지 않고 comment 테이블을 사용하는 이유는?
대댓글이란 다른 댓글에 달린 댓글으로 그 본질은 댓글이기 때문입니다.
대신 그냥 댓글과 대댓글을 구분해주기 위해 parent_comment 필드를 만들었습니다. 이 필드에 값이 있으면 대댓글이고, 아니면 그냥 댓글입니다.

Q. parent_comment 필드에 'self'는 무엇을 의미?
'self'는 자기 자신을 의미합니다. 하나의 댓글에 대해 여러 개의 대댓글이 달릴 수 있으므로, 1:N의 관계입니다. 따라서 ForeignKey로 자신이 속한 Comment 클래스를 참조합니다.
대댓글이 아닌 경우 parent_comment가 없을 수도 있으므로 null=True를 지정했습니다.

💣 View 작성

CommentView의 post함수에 대댓글 기능 추가

이미 댓글 등록 기능을 구현하기 위해 CommentView의 post 함수를 만들었습니다. 이 함수에서 대댓글을 생성할 수 있는 기능을 추가하도록 합시다. 단순히 parent_comment 정보를 함께 생성할 수 있게 하면 됩니다.

parent_comment_id = data.get('parent_comment_id', None)로 부모댓글 정보를 받습니다. 이 정보는 필수가 아니므로 전달되지 않을 경우 None이 할당되도록 하였고, KeyError 처리도 해주지 않았습니다.

content           = data.get('content', None)
posting_id        = data.get('posting_id', None)
parent_comment_id = data.get('parent_comment_id', None)  --> 추가

if not (content and posting_id):
    return JsonResponse({'message':'KEY_ERROR'}, status=400)

댓글 정보를 생성할 때도 parent_comment_id가 함께 생성되도록 합니다. (대댓글이 아닐 경우에는None이 입력될 것입니다.)

Comment.objects.create(
    content           = content,
    user              = user,
    posting           = posting,
    parent_comment_id = parent_comment_id  --> 추가
)

👀 전체 View 코드

class CommentView(View):
    @login_decorator
    def post(self, request):
        try:
            data = json.loads(request.body)
            user = request.user

            content           = data.get('content', None)
            posting_id        = data.get('posting_id', None)
            parent_comment_id = data.get('parent_comment_id', None)

            if not (content and posting_id):
                return JsonResponse({'message':'KEY_ERROR'}, status=400)

            if not Posting.objects.filter(id=posting_id).exists():
                return JsonResponse({'message':'POSTING_DOES_NOT_EXIST'}, status=404)
            
            posting = Posting.objects.get(id=posting_id)

            Comment.objects.create(
                content           = content,
                user              = user,
                posting           = posting,
                parent_comment_id = parent_comment_id
            )

            return JsonResponse({'message':'SUCCESS'}, status=201)
        
        except JSONDecodeError:
            return JsonResponse({'message':'JSON_DECODE_ERROR'}, status=400)

📬 url 경로 지정하기

url 경로는 동일합니다.

profile
Leave your comfort zone
post-custom-banner

0개의 댓글