DRF 4-10 상세페이지, List의 Serializer 수정

Grace Goh·2022년 11월 12일
0

Django Rest Framework

목록 보기
21/36

게시글 상세페이지에서

  • 좋아요 : pk가 아니라> 이메일로 표시되게
    (실제 front에서 처리할 때는 user 정보가 pk값으로 나오는 게 편리할 수 있다)

  • 댓글이 같이 나오도록

수정한다.

우선 게시글 상세페이지에 쓰이고 있는 Serializer는 ArticleSerializer다.

다음과 같이 SerializerMethodField()를 써서 user의 경우 email이 나오게 되어 있다.

# articles/serializers.py

class ArticleSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()

    def get_user(self, obj):
        return obj.user.email # 유저 이메일이 나오게 되어 있다.

    class Meta:
        model = Article
        fields = '__all__'

댓글을 불러오려면 comment와 article의 관계를 봐야 한다.

Article의 경우 다음과 같이 comment 섹션이 없다.

# articles/models.py

class Article(models.Model):
    # 한 user가 여러 article. 1:many. FK
    user = models.ForeignKey(User, on_delete=models.CASCADE) # 삭제할 때 없애준다
    title = models.CharField(max_length=50)
    content = models.TextField()
    image = models.ImageField(blank=True, upload_to='%Y/%m/')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    likes = models.ManyToManyField(User, related_name="like_articles")
     
    def __str__(self):
        return str(self.title)


class Comment(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    # FK로 Article을 참조한다. related_name 필요
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="comment_set")
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

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

Comment 쪽에서 FK로 연결이 되어 있다.
모델에서 comment가 FK로 Article을 참조하고 있을 때는 related_name으로 Article에서 Comment를 참조한다.

related_name이 설정이 안 되어 있을 경우 comment_set이 default다.
Article의 입장에서는 comment_set로 조회할 때 comment를 볼 수 있다.

여러 방식이 가능하지만

# articles/serializers.py

class ArticleSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()
    comment_set = CommentSerializer(many=True) # 추가

    def get_user(self, obj):
        return obj.user.email # 유저 이메일이 돌아가게 되어 있다.

    class Meta:
        model = Article
        fields = '__all__' # 팔드는 all로 되어 있어 자동으로 추가된다.
        
        
# 표시되는 댓글들의 형식은 CommentSerializer가 결정한다.
class CommentSerializer(serializers.ModelSerializer):
	user = serializers.SerializerMethodField() # 이메일 형식으로 표시

    def get_user(self, obj):
        return obj.user.email


    class Meta:
        model = Comment
        # fields = '__all__'
        exclude = ("article",) # 불필요한 정보 1개만 제외할 때는 exclude를 쓰기도 한다.

만약 모델에서 related_name을 설정한다면

# articles/models.py

class Comment(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="comments") # 설정
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

시리얼라이저에서도 다음과 같이 comment_set이 아니라 comments로 접근해야 POSTMAN에서 실행할 수 있다.

# articles/serializers.py

class ArticleSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()
    comments = CommentSerializer(many=True)

Likes

DRF Serializer relations 공식 문서
https://www.django-rest-framework.org/api-guide/relations/
원하는 기능 만들 때 유용하다. 꼭 읽어보기.

StringRelatedField

to represent the target of the relationship using its __str__ method.

# articles/serializers.py

class ArticleSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()
    comments = CommentSerializer(many=True)
    likes = serializers.StringRelatedField(many=True) # 추가
# users/serializers.py

class User(AbstractBaseUser):
	...
    def __str__(self):
        return self.email

조회해보면 (설정한 related_name) "comments" = [] 안에 댓글들이 나온다.

괄호 안의 괄호같은 방식을 Nested Relationship이라 한다.

https://www.django-rest-framework.org/api-guide/relations/
어려우니 drf 공식 문서를 참고하면서 한다.

likes_count, comments_count

모델에 없었던 부분이라도 함수를 이용해서 원하는 필드값을 추가할 수 있다.

# articles/serializers.py

class ArticleListSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()
    likes_count = serializers.SerializerMethodField()
    comments_count = serializers.SerializerMethodField()

    def get_user(self, obj):  # obj: 해당 article
        return obj.user.email

    def get_likes_count(self, obj):
        return obj.likes.count()

    def get_comments_count(self, obj):
        return obj.comments.count() # 변경 주의. cf. comments_set

    class Meta:
        model = Article
        fields = ("pk", "title", "image", "updated_at", "user", "likes_count", "comments_count")  # 추가

front에서 이 데이터를 이용해 구현한다.

profile
Español, Inglés, Coreano y Python

0개의 댓글