게시판의 추천 글 모아보는 기능을 구현해보고 싶었다.
# models.py
subject_list = [
('일반','일반'),
('정보','정보'),
('사진','사진'),
('공략','공략'),
('자랑','자랑'),
]
class Article(models.Model):
title = models.CharField(max_length=80)
content = models.TextField()
createuser = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
hits_field = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True, null=False, blank=False)
updated_at = models.DateTimeField(auto_now=True, null=False, blank=False)
subject = models.CharField(max_length=50, choices=subject_list)
def __str__(self):
return self.title
class LikeArticle(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='article_name')
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="article_like_user"
)
모델은 이렇게 구성되어있다.
추천수를 api에서 제공하기 위해 serializers.py
에서 아래와 같이 구현했다.
class ArticleSerializer(serializers.ModelSerializer):
images = serializers.SerializerMethodField()
createusernickname = serializers.ReadOnlyField(source='createuser.nickname')
hits = serializers.ReadOnlyField(source = 'hits_field')
comments = CommentNestedSerializer(many=True, read_only=True)
like_article = LikeArticleSerializer(many=True, read_only=True)
like_count = serializers.IntegerField(source="article_name.count", read_only=True)
그러나 serializer에서 만든 추천수로는 filter을 사용할 수 없었다.
그래서 view에서 annotate
를 활용하여 추천수로 필터링했다.
class BestArticleView(viewsets.ModelViewSet):
serializer_class = ArticleSerializer
queryset = Article.objects.annotate(count=Count('article_name')).filter(count__gt=30).order_by('-count')
annotate
란 가상의 속성을 만들어주는 것이다.
위의 코드에서 count
라는 가상의 속성을 만들고 이것을 Count('article_name')
라고 article_name
속성의 수라는 값을 주었다.
이 값을 filter
에서 사용하여 추천수 30으로 필터링 하는 방식이다.