📘 DRF 


목차

  1. 역참조 데이터 추가하기
  2. 커스텀 필드 추가하기
  3. 응답 구조만 변경하기
  4. 상속 활용하기

🤪 Serializer 활용하기

Serializer를 여러 가지 상황에 맞춰서 활용하는 방법을 알아봅시다!

 

1. 역참조 데이터 추가하기

👩🏻‍💼 동료 개발자 :
저희, Article 상세 조회하면 화면에서 댓글도 같이 보여야 해서요.
지금은 콜을 두 번해야 하는데, 콜을 하나로 묶어주실래요?

→ 우리가 할 일
{
    "id": 1,
    "title": "제목제목제목",
    "content": "내용내용내용",
    "created_at": "2023-12-28T08:02:08.364474Z",
    "updated_at": "2024-04-06T08:01:00.260880Z",
    "comments" : {
		    // 여기에 여러가지 코멘트가 함께 들어가면 좋을 것 같은데🤔
    }
    
}

 

Article에 Comment 추가하기

  • Nested Relationships 
    • Serializer는 기존 필드를 override 하거나 추가적인 필드를 구성할 수 있다.
      • 이때 모델 사이에 참조 관계가 있다면 해당 필드를 포함하거나 중첩할 수 있다.
  • 결국 우리가 조작해줘야할 것은~~ Serializer!
    • 현재 Article → Comments 접근이 필요 == 역참조
    • 역참조 시 사용할 수 있는 comment_set이 있으나 우리는 "comments"로 명명했다.(매니저 이름)
💡 아하!
"comments"라는 매니저 이름으로 된 필드를 다시 override 하는데, 표현 방식은 CommentSerializer를 사용하는구나.
# 모든 comments들을 CommentSerializer에 넘겨서 직렬화한 후, fields 추가해 줘!
    comments = CommentSerializer(many=True, read_only=True) # 오버라이딩

 

↓ 해보자

articles/serializers.py

더보기
변경 전

⬇️

변경 후
from rest_framework import serializers
from .models import Article, Comment

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = "__all__"
        read_only_fields = ("article",)

class ArticleSerializer(serializers.ModelSerializer):
    # 모든 comments들을 CommentSerializer에 넘겨서 직렬화한 후, fields 추가해 줘!
    comments = CommentSerializer(many=True, read_only=True) # 오버라이딩
    
    class Meta:
        model = Article
        fields = "__all__"

 

  1. CommentSerializer와 ArticleSerializer의 코드 위치를 바꿔주었어요
  2. ArticleSerializer에 comments 코드를 추가해주었어요
# 모든 comments들을 CommentSerializer에 넘겨서 직렬화한 후, fields 추가해 줘!
    comments = CommentSerializer(many=True, read_only=True) # 오버라이딩

 

 

코드 한 줄을 추가했을 뿐인데,

한 번에 댓글까지 조회할 수 있게 됐어요!


2. 커스텀 필드 추가하기

👩🏻‍💼 동료 개발자 :
저희 화면에 보면 댓글 수도 함께 표시가 되고 있어서요, 물론 데이터 받아와서 제가 카운트해도 되긴 하는데,
데이터 내려주실 때 한 번에 주실 수 있을까요?

 

댓글 수 필드 추가하기

  • "comments"의 경우 우리의 Django가 자동으로 추가해 주는 매니저이기에 바로 사용할 수 있었다.
  • 하지만 comments_count직접 필드를 추가해주는 것이 필요하다.
    • source 속성을 이용하여 데이터 값을 전달하는 것 가능하다.
    • 우리의 경우 Queryset API 중 하나인 count()를 이용하여 전달해주면 된다!
  • source
    • SerializerField의 속성으로 해당 필드를 채우는 데 사용하는 속성을 지정한다.
    • 점 표기법을 이용하여 내부 속성에 접근할 수 있다. (.count)
💡 아하!
# 댓글 갯수
    comments_count = serializers.IntegerField(source="comments.count", read_only=True)
    #.count가 ORM 함수​

 

↓ 해보자

articles/serializer.py

더보기
변경 전

⬇️

변경 후
from rest_framework import serializers
from .models import Article, Comment

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = "__all__"
        read_only_fields = ("article",)

class ArticleSerializer(serializers.ModelSerializer):
    # 모든 comments들을 CommentSerializer에 넘겨서 직렬화한 후, fields 추가해 줘!
    comments = CommentSerializer(many=True, read_only=True) # 오버라이딩
    # 댓글 갯수
    comments_count = serializers.IntegerField(source="comments.count", read_only=True) #.count가 ORM 함수
    
    class Meta:
        model = Article
        fields = "__all__"

 

  1. comments_count 코드를 추가했어요
# 댓글 갯수
    comments_count = serializers.IntegerField(source="comments.count", read_only=True)
    #.count가 ORM 함수

 

이외 많이 찾는 Fields

더보기

Serializer Method Fields
https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

SerializerMethodField()

from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = '__all__'

    def get_days_since_joined(self, obj):
        return (now() - obj.date_joined).days

 

 

get_days_since_joined 가 붙은 필드명의 함수가 실행되어 필드로 추가된다.


3. 응답 구조만 변경하기

👩🏻‍💼 동료 개발자 :
아래와 같은 댓글 조회에서 article로 내려오는 필드 삭제 부탁드릴게요. 오히려 헷갈려서요.
[
    {
        "id": 22,
        "content": "수정댓글",
        "created_at": "1972-09-02T22:34:52.315416Z",
        "updated_at": "2024-04-06T12:07:29.461800Z",
        "article": 1
    },
    {
        "id": 23,
        "content": "Try four often third side purpose. Detail require break believe arrive. Wonder avoid out network director.",
        "created_at": "2018-01-01T10:48:02.905154Z",
        "updated_at": "2017-04-27T18:30:10.763704Z",
        "article": 1
    },​

 

Custom fields 🔗

 

  • to_representation()
    • Serialization 이후 보이는 결과에 대해 자동으로 내부적으로 불리는 함수다.
    • 이 메서드를 override 하여 커스텀 형식으로 변경 가능하다.
💡 아하!
class CommentSerializer(serializers.ModelSerializer):

	# article 삭제(pop)
    def to_representation(self, instance):
        ret = super().to_representation(instance)
        ret.pop("article")
        return ret

 

↓ 해보자

articles/serializers.py

더보기
변경 전

⬇️

변경 후
class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = "__all__"
        read_only_fields = ("article",)
        
    # 댓글 목록에서 article 없애기
    def to_representation(self, instance):
        ret = super().to_representation(instance)
        ret.pop("article")
        return ret

 

  1. def to_representation을 추가했어요
    # 댓글 목록에서 article 없애기
    def to_representation(self, instance):
        ret = super().to_representation(instance)
        ret.pop("article")
        return ret

 

 

article이 없어졌어요!


4. 상속 활용하기

👩🏻‍💼 동료 개발자 :
죄송한데, 지금 게시글 목록 조회에서도 댓글 관련 필드들이 내려오고 있는데, 이건 상세 조회에서만 나오게 해 주세요.

 

💡 아하!
class ArticleDetailSerializer(ArticleSerializer):


class를 분리해서 사용하자!

 

↓ 해보자

1. articles/serializers.py

더보기
변경 전

⬇️

변경 후
class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = "__all__"
        

class ArticleDetailSerializer(ArticleSerializer):
    # 모든 comments들을 CommentSerializer에 넘겨서 직렬화한 후, fields 추가해 줘!
    comments = CommentSerializer(many=True, read_only=True) # 오버라이딩
    # 댓글 갯수
    comments_count = serializers.IntegerField(source="comments.count", read_only=True)
    #.count가 ORM 함수

 

article의 detail에서만 댓글과 댓글 수를 볼 수 있게끔 새로운 Serializer를 추가해 줬어요!

 

2. articles/views.py

더보기
변경 전

⬇️

변경 후

 

상세 목록에서만 댓글을 보고 싶기 때문에, Detail 부분만 다 수정해 주었어요

ArticleSerializer에서 ArticleDetailSerializer로 바꾸었어요

 

 

그러면 이제, 목록에선 댓글들이 보이지 않아요!

 

상세에서는 보여요!


 

+ Recent posts