[TIL] Django Westagram: like, comment, follow, reply to comment

Jene Hojin Choi·2021년 2월 6일
0

Django

목록 보기
7/12
post-thumbnail

import 부분이나 대부분의 부분은 생략되었고 일부분만 올렸다.
like, follow, comment에 관련한 것만 올렸다. login_decorator는 전글을 참고하면 좋을 것 같다!

1. user/models.py

from django.db import models

class User(models.Model):
    email           = models.EmailField(max_length=200, unique=True, verbose_name='Username')
    password        = models.CharField(max_length=300, verbose_name='Password') 
    nickname        = models.CharField(max_length=50)
    phone           = models.CharField(null=True, max_length=15)
    registered_time = models.DateTimeField(auto_now_add=True)
    updated_time    = models.DateTimeField(auto_now=True)
    
    class Meta:
        db_table = 'users'

class UserFollow(models.Model):
    follower  = models.ForeignKey('User', related_name='follower', on_delete=models.CASCADE)
    following = models.ForeignKey('User', related_name='following', on_delete=models.CASCADE) 
    
    class Meta:
        db_table = 'user_follow'
  • UserFollow 라는 클래스를 따로 만들어 follow를 하는 사람을 follower, follow 당하는 사람을 following이라고 저장하였다.
  • related_name 을 쓴 이유는 같은 클래스 UserFollow 에서 User를 두번 참조하기 때문인데, related_name을 쓰지 않으면 에러가 난다.

2. user/views.py

... 

class FollowView(View):
    @login_decorator
    def post(self, request):
        try:
            data         = json.loads(request.body)
            follower     = request.user
            follower_id  = follower.id
            following_id = data['following_id']
            
            if UserFollow.objects.filter(follower_id=follower_id, following_id=following_id).exists():
                UserFollow.objects.get(follower_id=follower_id, following_id=following_id).delete()
                return JsonResponse({'message': 'SUCCESS'}, status=200)

            UserFollow.objects.create(follower_id=follower_id, following_id=following_id)
            return JsonResponse({'message': 'SUCCESS'}, status=200)

        except KeyError: 
            return JsonResponse({'message':'KEY_ERROR'}, status=400)
  • 요청을 보내는 데이터에는 팔로우를 하는 사람의 정보 (그 전에 login을 하니까 토큰으로), 그 사람이 팔로우를 할 사람의 정보(following_id)를 담는다.
  • 이미 팔로우 한 사람을 다시 팔로우 하는 경우에는 언팔로우 하는 경우로 인식하여 delete를 진행한다.
  • 팔로우하지 않은 상태라면 팔로우를 한다.

3. post/models.py

... import, class Post 생략...

class Comment(models.Model):
    text         = models.CharField(max_length=200)
    posted_time  = models.DateTimeField(auto_now_add=True)
    updated_time = models.DateTimeField(auto_now=True) 
    post         = models.ForeignKey('Post', on_delete=models.CASCADE)
    user         = models.ForeignKey('user.User', on_delete=models.CASCADE)
    parent       = models.ForeignKey('self', null=True, blank=True, related_name='replies', on_delete=models.CASCADE)

    class Meta:
        db_table = 'comments'

class Like(models.Model):
    user        = models.ForeignKey('user.User', on_delete=models.CASCADE)
    post        = models.ForeignKey('Post', on_delete=models.CASCADE)
    liked_time  = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        db_table = 'likes'

class Comment

  • comment에 parent 이라는 attribute는 상위 댓글인지 아닌지 확인해준다. True이면 상위 댓글, False면 답글로 인식하도록 했다.
  • parent attribute는 Self를 써서 자기 자신을 참조할 수 있도록 했다. related_name 은 replies 이다.

class Like

  • like 클래스는 user와 게시글(post)을 참조하도록 했다.

4. post/views.py

...

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

              user      = request.user
              text      = data['text']
              post_id   = data['post_id']
              parent_id = data.get('parent_id', None) 

              if User.objects.filter(email=user.email).exists():
                  Comment.objects.create(
                      text = text,
                      post = Post.objects.get(id=post_id),
                      parent_id = parent_id,
                      user = user
                  )
                  return JsonResponse({'message':'SUCCESS'},status=200)

              return JsonResponse({'message':'INVALID_USER'},status=401)

          except KeyError: 
              return JsonResponse({'message':'KEY_ERROR'}, status=400)
              
  • request할 정보에는 comment의 내용, 댓글을 달 게시글의 아이디를 담았다. login을 해야하기 때문에 로그인한 유저의 토큰도 담는다.
  • parent_id 도 담았는데, 특정 댓글에 대한 답글이라면 부모 댓글을 요청에 보내고, 만약 자기자신이 부모 답글이라면 요청에 담아서 보내지 않는다.
  • 유저의 정보가 존재한다면 답글을 만들어준다.
  • 같은 comment는 작성할 수 있기 때문에 굳이 같은 내용의 댓글을 걸러준다던지 하는 기능은 만들지 않았다.
class LikeView(View):
    @login_decorator
    def post(self, request):
        try:
            data    = json.loads(request.body)

            user    = request.user
            post    = Post.objects.get(id=data['post_id'])

            if Like.objects.filter(post=post, user=user).exists():
                Like.objects.get(post=post, user=user).delete()
                like_counts = Like.objects.filter(post=post).count()
                return JsonResponse({'message':'SUCCESS', 'like_counts':like_counts},status=200)

            like = Like.objects.create(post=post, user=user)
            like_counts = Like.objects.filter(post=post).count()
            return JsonResponse({'message':'SUCCESS', 'like_counts':like_counts},status=200)

        except KeyError: 
            return JsonResponse({'message':'KEY_ERROR'}, status=400)
  • request할 정보에는 login을 해야하기 때문에 로그인한 유저의 토큰과 좋아할 게시글의 아이디를 담는다.
  • like를 이미 했을 경우에는 좋아요를 없애는 것으로 간주한다.
  • like_counts를 이용해 해당 게시글의 좋아요 수를 계산한다.
  • like가 없는 경우에는 좋아요를 하는 것으로 간주했다.

생각...

  • 실제 웹사이트나 프론트에 따라서 달라질 수 있는 부분은 내 맘대로 한 것이다. 내 마음대로 구현한 것이다보니 확실하지 않은 부분이 꽤 있다. 실제 현업에서는 어떻게 만드는지 궁금하다.
  • 고려해야할 다른 케이스가 있다면 추가 업데이트 할 예정이다.

0개의 댓글