DRF에서 Nested Serializer 사용법

DRF에서 Nested Serializer 사용법

2019, Feb 16    
  • 이번 글에서는 Serializer 안에 또 다른 Serializer가 중첩된 nested serializer 형태를 생성하는 방법에 대하여 알아보겠습니다.
  • 다양한 방법의 nested serializer가 있으며 상황에 따라 사용방법이 조금씩 다를 수 있습니다.

Nest serializer 사용 예시 목록

  • 1 : N 관계에서 1에 해당하는 model 기준으로 nested serializer 생성 (Reverse relations)
  • 1 : N 관계에서 N에 해당하는 model 기준으로 nested serializer 생성

1 : N 관계에서 1에 해당하는 model 기준으로 nested serializer 생성 (Reverse relations)

  • 참고 자료 : https://www.django-rest-framework.org/api-guide/relations/#reverse-relations
  • 1 : N 관계에서 1에 해당하는 model을 기준으로 nested serializer를 생성하는 방법에 대하여 알아보겠습니다.
    • 이 방법을 djangro restframework에서는 Reverse relations 라고 정의하였습니다.
  • 1 : N 관계이므로 1에 해당하는 model의 Primary Key를 N에 해당하는 모델에서 Foreign Key로 사용하고 있습니다.
  • 아래 예제는 ModelSerializer를 기준으로 작성하였습니다.


  • 아래 코드에서 Album : Track = 1 : N의 관계를 가집니다.
  • reverse relation을 정의하려면 Serializer의 field에 정의를 해야 합니다.
    • AlbumSerializer 클래스 내부에 tracks = TrackSerializer(many=True, read_only=True) 이 있습니다.
class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ('order', 'title', 'duration')

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')


  • 만약 위 코드 처럼 AlbumSerializer 내부에 tracks라는 변수명으로 입력을 받기 위한 조건
    • Track 모델 내부의 album 모델 관련 Foreign Key에서 related_name으로 tracks를 지정해 주어야 합니다.
class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)


  • 만약 Foreign Key에서 related name을 지정해 주지 않는 다면 기본 값인 모델명_set으로 설정할 수 있습니다.
  • related name을 설정하지 않은 경우 AlbumSerializer에서 따로 Trackserializer()를 통하여 할당 받지 않고 field 명에 track_set으로 사용 가능합니다.
class AlbumSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ('track_set', ...)


  • related_name 지정 유무와 상관없이 결과는 동일하고 nested serializer 결과는 다음과 같습니다.
  • Album의 Primary Key에 해당하는 모든 Track 모델의 값을 join 해서 리턴해 줍니다.
    'album_name': 'Sometimes I Wish We Were an Eagle',
    'artist': 'Bill Callahan',
    'tracks': {
        'Track 1: Jim Cain (04:39)',
        'Track 2: Eid Ma Clack Shaw (04:19)',
        'Track 3: The Wind and the Dove (04:34)',
        ...
    }



1 : N 관계에서 N에 해당하는 model 기준으로 nested serializer 생성

  • 위의 예제에서는 1 : N의 관계에서 1에 해당하는 model의 Serializer에서 nested serializer를 생성하였습니다.
  • 이번에는 1 : N의 관계에서 N에 해당하는 model의 Serializer에서 nested serializer를 만들어 보겠습니다.
  • 이번 예제는 Child와 Parent 입니다. 한명의 Child에게는 2명의 부모님이 있으니 Child : Parent = 1 : N 의 관계 입니다.
class Child(models.Model):
    name = CharField(max_length=20)

class Parent(models.Model):
    name = CharField(max_length=20)
    phone_number = models.ForeignKey(PhoneNumber)
    child = models.ForeignKey(Child)

class ChildSerializer(ModelSerializer):
    class Meta:
        model = Child
        fields = '__all__'


class ParentSerializer(ModelSerializer):
    class Meta:
        model = Parent
        fields = '__all__'

    def to_representation(self, instance):
        response = super().to_representation(instance)
        response['child'] = ChildSerializer(instance.child).data
        return response


  • 여기서 핵심은 ParentSerializer에 override 된 to_representatin입니다.
    • response[모델명] = ModelSerializer(instance.ForeingKeyField).data 로 선언하면 됩니다.
    • 위 예제에서는 response[‘child’] = ChildSerializer(instance.child).data
  • 위 코드와 같이 구성 시 list를 조회하면 아래와 같이 결과를 리턴 받습니다.
{
    "id" : 4,
    "name" : "parantname",
    "phone_number" : 123-123,
    "child" : {
        "id" : 1,
        "name" : "childname"
    }
    
}