지난 시간에는 게시물 및 댓글 삭제, 수정 기능을 구현하였습니다. 이번에는 대댓글 기능을 구현하도록 하겠습니다. 마찬가지로 로그인 데코레이터를 사용해서 로그인된 권한있는 유저만이 대댓글 기능을 사용할 수 있도록 하겠습니다.
하나의 댓글에 대해 여러 개의 대댓글이 달릴 수 있습니다.(1:N)
대댓글 기능은 게시물과 관련되어 있으므로 posting
앱에서 작성합니다.
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
를 지정했습니다.
이미 댓글 등록 기능을 구현하기 위해 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 --> 추가
)
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 경로는 동일합니다.