본문 바로가기
카테고리 없음

2023-06-12 좋아요 5종 반응

by jung1911 2023. 6. 12.

설명

프로젝트 주제가 기사 페이지 인데 게시글에 5종 반응 즉 좋아요 슬퍼요 화나요 대단해요 후속 요청 등 이런 반응들을 구현 

 

models.py

1.db를 나눠서 반응을 나눌려고 한다.

2.반응들을 Many to Many 필드로 설정해서 시리얼라이저를 통해 끝을 낼 수 있을거라고 생각했다.

- M to M을 사용해 다대다 즉 a테이블 b테이블을 서로를 참조할 예정

######게시글######


class ArticleLike(models.Model):
     article = models.ForeignKey(Article, on_delete=models.CASCADE, verbose_name="해당 댓글")
     user = models.ForeignKey(User, on_delete=models.CASCADE)

 class ArticletHate(models.Model):
     article = models.ForeignKey(Article, on_delete=models.CASCADE, verbose_name="해당 댓글")
     user = models.ForeignKey(User, on_delete=models.CASCADE)

      def __str__(self):
        return str(self.article)

    like = models.ManyToManyField(User, blank=True, related_name="like")
    sad = models.ManyToManyField(User, blank=True, related_name="sad")
    angry = models.ManyToManyField(User, blank=True, related_name="angry")
    good = models.ManyToManyField(User, blank=True, related_name="good")
    subsequent = models.ManyToManyField(User, blank=True, related_name="subsequent")

 

문제 
에러가 발생  Postman에서 확인을 하니 아무런 반응도 안나옴.

시도

그러면 반응들만 따로 빼서 시도를 해보면 어떨까? 
반응을 따로 빼서 시도를 해보니 일단 반응은 나온다. 

하지만 반응만 나올뿐 아무런 반응은 생기지 않았다.

불( BoleanField)값을 사용해서 DB를 합쳐서 한번에 해보면 어떨까? 라는 생각으로 다시 시도!

# 게시글 반응#
 
 like = models.ManyToManyField(User, blank=True, related_name="like")
    sad = models.ManyToManyField(User, blank=True, related_name="sad")
    angry = models.ManyToManyField(User, blank=True, related_name="angry")
    good = models.ManyToManyField(User, blank=True, related_name="good")
    subsequent = models.ManyToManyField(User, blank=True, related_name="subsequent")

 

 

2번째 시도

오! 이렇게 하니깐 반응이 나왔다.!  

왜 M to M 으로 하면 안되는걸까? 혼자 깊게 생각하기 시작..

생각해보니 감정은 5가지 한 유저가 사용을 하니깐 일 대 다 또는 다 대 일 관계로 사용되어야한다.그러니 다대다는 아무런 반응이 없는게 맞다.

class ArticleReaction(models.Model):
    class Meta:
        db_table = "Articlereaction"

    article = models.ForeignKey(Article, on_delete=models.CASCADE, verbose_name="해당 게시글")
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    great = models.BooleanField(default=False)
    sad = models.BooleanField(default=False)
    angry = models.BooleanField(default=False)
    good = models.BooleanField(default=False)
    subsequent = models.BooleanField(default=False)
    
    def __str__(self):
        return str(self.article)

 

 

serializers.py

이제 어떻게 직렬화 할꺼냐? 여기서 Articleseralizer 에서 반응이 나오도록 할려고한다. 

1.초기 값을 0으로 설정하고 1 이되도록 직렬화.

2.사용해도 반응은 클릭이 되지만 카운트가 안되는 오류가 발생한다.

 def get_reaction(self, obj):
        reaction_data = {
            'like': 0,
            'sad': 0,
            'angry': 0,
            'good': 0,
            'subsequent': 0
        }
        reaction = obj.articlereaction_set.all()
        for reaction in reaction:
            if reaction.like:
                reaction_data['like'] += 1
            elif reaction.sad:
                reaction_data['sad'] += 1
            elif reaction.angry:
                reaction_data['angry'] += 1
            elif reaction.good:
                reaction_data['good'] += 1
            elif reaction.subsequent:
                reaction_data['subsequent'] += 1
        return reaction_data

 

시도
아쉽지만 전부다 지우고 count를 사용해서 카운트를 하면 될 거같다.
훨씬 깔끔하고 알아보기 쉽게 되었다.

사용해보니 동작도 잘된다.

애초에 카운트를 사용한 방법을 생각한거 아니다 하지만 저런식의 방법도 될거 같아서 사용해봤지만.. 좀 아쉽다.

def get_reaction(self, obj):
        reaction_data = {
            'great': obj.great.count(),
            'sad': obj.sad.count(),
            'angry': obj.angry.count(),
            'good': obj.good.count(),
            'subsequent': obj.subsequent.count()
        }
        return reaction_data

 

 

views.py

예외처리를 사용해서 하는 코드가 유지보수및 오류에 찾기에 좋다.

그래서 예외 처리를 이용한 코드를 계속 짜보면서 하는중이다.

여기서 getattr 를 사용해서 반응들의 속성을 가져오도록 사용

 

getattr - 세 개의 인수를 받는다.

객체 obj("lee", 25)

속성 이름 name

기본 값 age

객체의 속성 동적으로 가져온다.  

속성이 존재하지 않으면 AttributeError 라는 오류가 발생 

아직 이해가 잘 안되지만 좀 더 응용해보면서 사용하면 이해가 될거 같다.

class ArticleReactionView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, article_id):
        try:
            article = get_object_or_404(Article, id=article_id)
        except Article.DoesNotExist:
            return Response({"error": "게시글이 없습니다."}, status=404)

        reaction = request.data.get('reaction')

        if reaction in ['great', 'sad', 'angry', 'good', 'subsequent']:
            reaction_field = getattr(article, reaction) #getattr 를 사용

            if request.user in reaction_field.all():
                # 사용자가 이미 반응을 한 상태이므로 반응을 취소
                reaction_field.remove(request.user)
                return Response({"message": "반응을 취소했습니다."}, status=status.HTTP_200_OK)
            else:
                # 사용자가 반응을 하지 않은 상태이므로 반응을 추가
                reaction_field.add(request.user)
                return Response({"message": "반응을 눌렀습니다."}, status=status.HTTP_201_CREATED)
        else:
            return Response({"error": "유효하지 않은 반응 타입입니다."}, status=status.HTTP_400_BAD_REQUEST)

댓글