Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- django
- *args
- 알고리즘
- decorator
- 인터넷 네트워크
- 윈도우우분투듀얼부팅
- 파이썬
- 해시충돌
- 코딩테스트파이썬
- 파이썬리스트컴프리헨션
- clone coding
- docker
- 자바스크립트
- 리스트컴프리헨션
- clone-coding
- **kwargs
- 파이썬문법
- JavaScript
- wecode
- promise
- QuerySet
- DP
- 자료구조
- 백준
- RESTfulAPI
- bcrypt
- 인증인가
- CSS
- 파이썬입출력
- Python
Archives
- Today
- Total
개발기록장
[Django] 인스타그램 클론 코딩(7) - 대댓글 기능 구현 본문
[이전 글]
[Django] 인스타그램 클론 코딩(6) - 팔로우(follow) 기능 구현
인스타그램에서 대댓글은 상위 댓글과 1:M 관계이다.
나는 대댓글 모델(테이블)을 따로 두지 않고 기존 Comment 모델에 parent라는 attribute를 추가하여 ForeignKey로 자기 자신을 참조하게 하였다.
1. post/models.py
from django.db import models
from user.models import User
class Comment(models.Model):
user = models.ForeignKey('user.User', on_delete=models.CASCADE)
post = models.ForeignKey('Post', on_delete=models.CASCADE)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True)
content = models.CharField(max_length=500)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'comments'
- 기존 Comment모델에서 parent라는 attribute를 추가하였다.
- 여기에 ForeignKey로 참조하는 테이블을 'self'로 지정하여 1:M 셀프 참조를 구현하였다.
- 대댓글일 경우에 parent 값으로 상위 댓글의 id(PK)가 들어오게 된다.
- 가장 최상위 댓글은 parent에 Null이 되므로 null=True 옵션을 설정해주었다.
2. post/views.py (댓글 및 대댓글 CRUD)
import json
from json.decoder import JSONDecodeError
from django.views import View
from django.http import JsonResponse
from .models import Post, Comment, Like
from user.models import User
from user.utils import login_decorator
class CommentView(View):
@login_decorator
def post(self, request):
data = json.loads(request.body)
user = request.user
post_id = data.get('post', None)
parent_id = data.get('parent', None)
content = data.get('content', None)
# KEY_ERROR check
if not (post_id and content):
return JsonResponse({'message': 'KEY_ERROR'}, status=400)
# valid post check
if not Post.objects.filter(id=post_id).exists():
return JsonResponse({'message': 'INVALID_POST'}, status=400)
# valid comment check
if parent_id and not Comment.objects.filter(id=parent_id).exists():
return JsonResponse({'message': 'INVALID_COMMENT'}, status=400)
Comment.objects.create(
user = user,
post = Post.objects.get(id=post_id),
parent_id = parent_id,
content = content
)
return JsonResponse({'message': 'SUCCESS'}, status=200)
class CommentDetailView(View):
# update
@login_decorator
def post(self, request, comment_id):
try:
data = json.loads(request.body)
content = data.get('content', None)
# KEY_ERROR check
if not content:
return JsonResponse({'message': 'KEY_ERROR'}, status=400)
# vaild comment check
if not Comment.objects.filter(id=comment_id).exists():
return JsonResponse({'message': 'INVALID_COMMENT'}, status=400)
comment = Comment.objects.get(id=comment_id)
# valid user check
if comment.user != request.user:
return JsonResponse({'message': 'INVALID_USER'}, status=401)
comment.content = content
comment.save()
return JsonResponse({'message': 'SUCCESS'}, status=200)
except JSONDecodeError:
return JsonResponse({'message': 'REQUEST_BOBY_DOES_NOT_EXISTS'}, status=400)
@login_decorator
def delete(self, request, comment_id):
# vaild comment check
if not Comment.objects.filter(id=comment_id).exists():
return JsonResponse({'message': 'INVALID_COMMENT'}, status=400)
comment = Comment.objects.get(id=comment_id)
# valid user check
if comment.user != request.user:
return JsonResponse({'message': 'INVALID_USER'}, status=401)
comment.delete()
return JsonResponse({'message': 'SUCCESS'}, status=200)
class PostDetailView(View):
def get(self, request, post_id):
# valid post check
if not Post.objects.filter(id=post_id).exists():
return JsonResponse({'message': 'INVALID_POST'}, status=404)
context = {}
# post 정보
post = Post.objects.get(id=post_id)
context['user'] = post.user.name
context['image_url'] = post.image_url
context['content'] = post.content
context['created_at'] = post.created_at
# comment 정보
comments = Comment.objects.filter(post=post)
if comments:
comment_list = []
for comment in comments:
# 대댓글이 있을 경우와 없을 경우를 나눠서 처리
if comment.parent:
parent_id = comment.parent.id
else:
parent_id = None
comment_list.append({
'user' : comment.user.name,
'parent_id' : parent_id,
'content' : comment.content,
'created_at': comment.created_at
})
context['comment_list'] = comment_list
return JsonResponse({'data': context}, status=200)
-
CommentView
-
post 메소드 : 기존에 댓글 작성과 동일. 대댓글일 경우, request body에서 parent 댓글의 id를 받아온다고 가정해서 코드를 작성하였다. 대댓글이 아닐 경우에는 parent_id에 None 값이 들어감으로써 그냥 댓글과 대댓글을 구분할 수 있게 하였다.
-
-
CommentDetailView
-
post 메소드 : 기존 댓글 수정과 동일
-
delete 메소드 : 기존 댓글 삭제와 동일
-
-
PostDetailView
-
get 메소드 : 특정 게시물과 그 게시물에 달린 댓글, 대댓글 데이터까지 보여주는 view이다. 댓글이 있을 경우 또는 대댓글이 있을 경우에만 response로 넘겨준다.
-
'TIL > Django' 카테고리의 다른 글
[Django] Path parameter와 Query parameter (0) | 2021.02.28 |
---|---|
[Django] Q객체를 이용한 ORM 조건절 (2) | 2021.02.28 |
[Django] 인스타그램 클론 코딩(6) - 팔로우(follow) 기능 구현 (0) | 2021.02.10 |
[Django] 인스타그램 클론 코딩(5) - 좋아요(Like) 기능 구현 (0) | 2021.02.09 |
[Django] 인스타그램 클론 코딩(4) - 게시물과 댓글 C.R.U.D (RESTful API) (0) | 2021.02.09 |