(Django) ajax를 이용한 댓글과 재댓글 구현하기 - 2
② 재댓글 구현하기
전체적인 코드의 로직 설명은 댓글 구현하기 - ① 에 작성되어 있으니 해당 글을 참고하자 :-)
1. model 설계
recomment 모델을 생성한다. 대댓글은 여러개의 댓글에 달릴 수 있기 때문에 n:n으로 설정했다 (지금보니 1:n이 더 맞을것 같은 느낌이 들기는 한다..)
# social/models.py
class ReComment(TimeStampable):
content = models.CharField(max_length=255)
writer = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='re_comment')
comment = models.ManyToManyField(Comment, related_name='re_comment',blank=True)
2. view 설계
댓글과 마찬가지로 recomment의 dto를 생성해준다. 이때 모델에 있는 데이터뿐만 아니라 ajax 를 통해 받는 데이터도 생각해서 작성하였다.
# social/dto.py
@dataclass
class ReCommentDto():
content:str
writer: User
created_at: int
user_pk:str
comment_pk:str
article_pk:str
2. ajax에서 보낸 데이터를 받아 dto에 맞게 데이터를 넣어주고 보내준다
- ajax에서 보내온 데이터를 data변수에 담는다
- 이전에 만들었던 dto형식에 맞게 데이터를 넣어준다
- dto에 들어간 데이터들을 가공하기 위해 우선 recomment_dto에 담는다
- 담은 recomment_dto를 social/service 로직에 보내준다.
# social/views.py
class ReCommentView(View):
def post(self, request):
if request.is_ajax():
data = json.loads(request.body) -- 1
recomment_dto = self._build_recomment_dto(request,data) - 3
context = SocialService.create_recomment(recomment_dto) - 4
return JsonResponse(context)
@staticmethod
def _build_recomment_dto(request,data): - 2
return ReCommentDto(
content = data.get('re_comment'),
writer = request.user,
created_at = time.time(),
user_pk = data.get('user_pk'),
comment_pk = data.get('comment_pk'),
article_pk = data.get('article_pk')
)
3. view에서 보낸 데이터를 알맞게 가공해준다
- dto:ReCommentDto를 작성해준 이유는 해당 dto 데이터가 ReComment라는 것을 명시적으로 보여주기 위해 작성한 것이다.
- 해당 dto데이터에 .을 통해 접근하여 필요한 데이터들을 가져온다. 여기서 나는 comment나 recomment filter에 관한건 social/service/SocialFilterService에서 가져왔다.
- ReComment, 즉 대댓글을 create해준다. 이때 recomment에 comment는 n:n이기 때문에 add를 통해 recomment에 추가해준다
- 댓글과 다른점은 댓글에 존재하는 대댓글은 n:n으로 묶여있기 때문에 for문을 통해서 데이터들의 정보를 가져온다
- 댓글과 마찬가지로 context를 생성하는 함수에 딕셔너리 형태로 데이터를 넣어 context를 작성한다
class SocialService():
# social/service.py
class SocialService():
@staticmethod
def create_recomment(dto:ReCommentDto): - 1
comment = SocialFilterService.find_by_comment_infor(dto.comment_pk) - 2
user = UserFilterService.find_user_infor(dto.user_pk).username
profile_nickname = UserFilterService.find_profile_infor(dto.user_pk).nickname
recomment = ReComment.objects.create( - 3
content = dto.content,
writer = dto.writer,
created_at = dto.created_at
)
recomment.comment.add(comment)
recomment_contents = {} - 4
for recomment in comment.re_comment.all():
recomment_contents[recomment.id] = {
'id':recomment.id,
'created_at':get_time_passed(recomment),
'updated_at':recomment.updated_at,
'content':recomment.content,
'writer_pk':recomment.writer.pk,
'writer':recomment.writer.username,
'user_img': recomment.writer.profile.image.url,
'profile_nickname':profile_nickname
}
context = context_infor( - 5
re_content = dto.content,
user = user,
comment_data = model_to_dict(comment),
recomment_created = get_time_passed(recomment),
comment_user_img = comment.writer.profile.image.url,
recomment_obj = recomment_contents,
)
return context
4. 템플릿에서 이제 해당 데이터들을 받아 알맞게 화면에 뿌려주면 된다
댓글과 주의해야할 상황이 똑같다.
대댓글의 html 코드를 보고 싶다면 여기를 클릭해서 보면된다
댓글과 마찬가지로 코드가 복잡해보인다. (특히 javascript..) 이유는 댓글과 독가타. 판매자의 댓글과 방문자의 댓글, 그리고 각 유저의 이미지와 댓글 단 시간 등 정보들을 나우어 화면에 보여주기 때문이다
이렇게 대댓글 구현은 끝이 났다. ! github에 있는 코들를 참고하면서 구현해본다면 훨씬 이해하기 좋을것 같다