Westagram #8 : 대댓글 기능 구현 + self 참조

채록·2021년 2월 13일
2

Python & Django

목록 보기
23/34
post-thumbnail

대댓글 기능 구현

대댓글의 형식은 크게 두가지 있다.
1. 오리진 댓글에 여러개의 대댓글이 수평적 구조로 달리기
2. 오리진 댓글에 달린 대댓글에 또다른 댓글이 달리는 계단식 구조

나의 경우 첫번째 모델을 기준으로 작성하고자 한다. (실제 인스타에서도 1번과 같은 구조이다.)




기능 Flow

생각보다 구조를 짜는게 쉽지 않았다.
또다른 대댓글 table을 만들자니 그렇게 되면 한 댓글에 대한 대댓글의 정보가 담길 수많은 table이 감당이 안된다.
기존의 댓글 table을 사용하되, 그 글이 오리진 댓글인지, 어떤 댓글에 대한 대댓글인지 판별할수 있도록 추가적인 field를 생성해야 겠다 생각했다.


models.py

class Comment(models.Model):
    posting     = models.ForeignKey(Posting, on_delete=models.CASCADE)
    user        = models.ForeignKey(User, on_delete=models.CASCADE)
    comment     = models.CharField(max_length=100)
    create_at   = models.DateTimeField(auto_now_add=True)
    parent      = models.ForeignKey('self', on_delete=models.CASCADE, related_name='recomment', null=True)

    class Meta:
        db_table = 'comments'
  • 자기자신을 참조할 때에도 역시 related_name을 지어준다.! 에러가 궁금하다면 직접! 해보기!

더욱 자세한 내용은 이전에 작성한 self ForeignKey설정 에 작성해두었다. (django shell로 create 한것도 담겨있다.)




views.py

CommentView에서 GET 으로 요청이 들어왔을때 그 응답으로
1. 모든 게시물에 달린 전체적인 댓글을 보여줄 것인가
2. 한 게시물에 달린 댓글들을 보여줄 것인가
3. 한 게시물의 댓글에 달린 대댓글들만을 보여줄 것인가

로 나눌수 있다고 생각했다. 때문에 기존의 CommentView의 get 메소드에서는 url로 아무런 id를 받지 않고, CommentDetailView의 get 메소드에서는 게시물의 id값을 받는것과 게시물의 id값 + 댓글의 id값 총 두개의 값을 url로 순차적으로 받게 것으로 두가지 경로를 설정해두었다.

# posting / urls.py
path('/comment', CommentView.as_view()),
path('/comment/<int:posting_id>', CommentDetailView.as_view()),
path('/comment/<int:posting_id>/<int:comment_id>', CommentDetailView.as_view())

  • 정보가 담긴 list가 비어있다면 NO_COMMENT혹은 NO_RECOMMENT로 메세지를 보낸다.
  • !! url 경로를 줄이고자 대댓글의 get을 comment_id만 받게 하면 django는 그 번호가 positng껀지 comment껀지 모른다.!! 그러므로 다른 형태의 url 경로를 지정해 주어야 한다.



HTTP Request

1. CommentView : 모든 댓글

http GET 127.0.0.1:8000/posting/comment
HTTP/1.1 200 OK
        {
            "comment": "그럼이것도되나?",
            "id": 3,
            "name": "yes",
            "posting_id": 2
        },
        {
            "comment": "됩니다용!",
            "id": 16,
            "name": "who",
            "posting_id": 2
        },
        {
            "comment": "안경 어디서 샀니?",
            "id": 65,
            "name": "bear",
            "posting_id": 53
        }

2. CommentDetailView : 한 게시글의 댓글

http GET 127.0.0.1:8000/posting/comment/2
HTTP/1.1 200 OK
        {
            "comment": "그럼이것도되나?",
            "id": 3,
            "name": "yes",
            "posting_id": 2
        },
        {
            "comment": "됩니다용!",
            "id": 16,
            "name": "who",
            "posting_id": 2
        }

3. CommentDetailView : 한 댓글의 대댓글

http GET 127.0.0.1:8000/posting/comment/2/3
HTTP/1.1 200 OK
{
    "result": [
        {
            "Up_comment": 3,
            "comment": "됩니다용!",
            "name": "who"
        }
    ]
}
  • Up_comment : 오리진 댓글의 id값을 의미한다.
  • 2번 게시글의 3번 오리진 댓글



인스타 목표과제가 끝났다!!!!!! 실제 인스타는 더 복잡한 로직으로 구성되어있겠지만 나는 초짜이므로 간단하게 동작될만큼만 구현했다!! 나중에 더 배워서 나도 복잡한 로직을 짤수 있으면 좋겠다. 이렇게 창업의 길을,, = 폭망




🔥🔥🔥🔥 잘못 사용한 개념 (21.02.19 추가)

related_name 개념을 잘못 이해하고 사용했다. 다시 작성한 포스팅을 참고한다.

위 개념을 다시 공부하고 코드를 바꾸면 다음과 같다.

class Comment(models.Model):
    posting     = models.ForeignKey(Posting, on_delete=models.CASCADE)
    user        = models.ForeignKey(User, on_delete=models.CASCADE)
    comment     = models.CharField(max_length=100)
    create_at   = models.DateTimeField(auto_now_add=True)
    parent      = models.ForeignKey('self', on_delete=models.CASCADE, related_name='origin_comment', null=True)

    class Meta:
        db_table = 'comments'
profile
🍎 🍊 🍋 🍏 🍇

0개의 댓글