1.머신러닝 팀 프로젝트 - annotate()
문제점
모델이 가지고 있지 않은 ForeignKey 필드의 Count를 기준으로 정렬해야함
class Article(models.Model):
user = models.ForeignKey(
User, verbose_name="작성자", on_delete=models.CASCADE, related_name="user_articles"
)
title = models.CharField("제목", max_length=30)
content = models.TextField("내용", null=True)
created_at = models.DateTimeField("작성시간", auto_now_add=True)
updated_at = models.DateTimeField("수정시간", auto_now=True)
like = models.ManyToManyField(
User, verbose_name="좋아요", related_name="like_article", blank=True
)
def __str__(self):
return str(self.title)
class HomeSerializer(serializers.ModelSerializer):
like_count = serializers.SerializerMethodField()
comments_count = serializers.SerializerMethodField()
def get_like_count(self, obj):
return obj.like.count()
def get_comments_count(self, obj):
return obj.comment_set.count()
class Meta:
model = Article
fields = "__all__"
serializer로 field를 생성하고 그 값을 get_필드명으로 생성했지만, 정렬이 불가능
class HomeView(APIView):
def get(self, request):
articles = Article.objects.all()
current_order = request.query_params.get("order_by")
if current_order == "latest":
articles = Article.objects.order_by("-created_at")
elif current_order == "likes":
articles = Article.objects.order_by("-like_count")
elif current_order == "comments":
articles = Article.objects.order_by("-comments_count")
기존에 가지고 있는 'created_at' 필드만 정렬이 가능함
시도해 본 것들
django order by로 구글 검색
annotate 키워드 발견
annotate() ≒ lambda()
람다가 함수를 임시로 생성해서 사용하는 것 처럼
annotate()는 field를 임시로 만들어준다.
Article.objects.annotate(comments_count=Count("comment")).order_by("-comments_count")
"comment"는
class Comment(models.Model):
article = models.ForeignKey(Article, verbose_name="게시글", on_delete=models.CASCADE)
user = models.ForeignKey(User, verbose_name="작성자", on_delete=models.CASCADE)
content = models.CharField("내용", max_length=300)
article을 ForeingKey로 가지고있는 Comment를 가져와서 사용한다.
그리고 그것을 comments_count=를 통해서 필드명을 지정해주고.order_by()로 정렬한다.
comments_count = serializers.SerializerMethodField()
def get_comments_count(self, obj):
return obj.comment_set.count()
그리고 serializer를 통해서 개수를 센 것을 보여준다.
serializer의 필드와 annotate()의 필드는 전혀 영향을 주지 않는 별개의 기능을 수행한다.
해결 방법
def get(self, request):
articles = Article.objects.all()
current_order = request.query_params.get("order", None)
if current_order == "outdated":
articles = Article.objects.order_by("created_at")
elif current_order == "likes":
articles = Article.objects.annotate(likes_count=Count("like")).order_by(
"-likes_count")
elif current_order == "comments":
articles = Article.objects.annotate(
comments_count=Count("comment")
).order_by("-comments_count")
elif current_order == None:
articles = Article.objects.order_by("-created_at")
알게 된 점
사용방법이 다를 뿐 구조 자체는 비슷한 명령어가 패키지에 많다는 것을 느꼈다.
annotate()를 통해서 임시로 Article에 필드로 활용한다.
뭔가 정리가 안되는 것 같아서 살펴보자 정렬 자체는 serailizer와 상관없이 annotate()단독으로 가능했다.
serailizer의 필드는 단순히 결과를 보여줄 수 있도록 세어주는 것이고 기능 자체에 영향을 주지는 않는다.
'개발일지 > TIL' 카테고리의 다른 글
TIL 23-05-30 백준 - 폴리오미노 (0) | 2023.05.30 |
---|---|
TIL 23-05-29 머신러닝 팀 프로젝트 - KPT 회고 (0) | 2023.05.29 |
TIL 23-05-26 머신러닝 팀 프로젝트 - 테스트 코드 (0) | 2023.05.26 |
TIL 23-05-25 머신러닝 팀 프로젝트 - git issue (0) | 2023.05.25 |
TIL 23-05-24 머신러닝 프로젝트 - git commit --amend (0) | 2023.05.24 |