본문 바로가기
파이썬(Python)/장고(Django)

[기초] 파이썬 장고 REST API - Nested Relationships

by 기계공학 주인장 2024. 2. 15.
반응형

이전 포스팅에서 Relationships에 대해 알아봤습니다.

 

https://android-developer.tistory.com/85

 

[기초] 파이썬 장고 REST API - Relationship 설정하기

이전 포스팅에서 Model Serializers를 사용하여 Model을 사용하는 방법에 대해 알아봤습니다. https://android-developer.tistory.com/84 [기초] 장고 REST API 프레임워크 - Model Serializer 이번 포스팅에서는 Model을 만

android-developer.tistory.com

 

이번에는 다수의 Model을 연결하는 Nested Relationships에 대해 알아보겠습니다. 

  • Relationships를 사용하여 특정 아이템을 서로 묶기
  • Nested Relationships 사용하기

Relationships를 사용하여 특정 아이템을 서로 묶기

이전 포스팅에서 저희는 기존에 있는 Movies라는 Model 이외에 StreamPlatform이라는 Model을 새롭게 만들었습니다.

 

Nested Relationships를 적용하기 전에 MoviesStreamPlatform 사이에 Relationships를 만들어보겠습니다.

 

먼저 Movie Model을 다음과 같이 변경합니다.

 

class StreamPlatform(models.Model):
    # Model(=DB)에서 사용할 Column 정의
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=50)
    about = models.TextField(max_length=200)
    website = models.URLField(max_length=100)

    def __str__(self):
        return self.name


class Movie(models.Model):
    # Model(=DB)에서 사용할 Column 정의
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=50)
    description = models.TextField(max_length=200)
    # StreamPlatform은 여러 개의 Movie를 가질 수 있음
    platform = models.ForeignKey(StreamPlatform, on_delete=models.CASCADE, related_name='movie')
    active = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

 

ForeignKey를 사용하여 StreamPlatform을 아이템으로써 가질 수 있도록 합니다.

 

그러면 admin에서 다음과 같은 항목이 추가된 것을 확인할 수 있습니다.

 

admin - Movies에 들어가서 아이템을 추가해보면

 

admin - Movies Model

 

사진과 같이 Platform 부분이 생성된 것을 알 수 있습니다.

 

해당 Platform에서 다음과 같이 생성해놓은 Platform을 선택할 수 있게됩니다.

 

 

Platform을 선택하면 다음과 같이 Movies 아이템에서 Platformid로 값이 표시되어있는 것을 알 수 있습니다.

 

/movie/list/

 

/movie/stream/


Nested Relationships 사용하기

지금까지의 과정으로 MovieStreamPlatform이라는 2개의 model을 생성했습니다.

 

이름에서 알 수 있다시피 StreamPlatform은 스트리밍 플랫폼이며 이는 많은 Movie를 가질 수 있음을 의미합니다.

 

즉, StreamPlatform ModelMovie Model을 가질 수 있습니다.

 

이를 Nested Relationships라고 합니다.

 

공식 문서는 다음과 같습니다.

 

Serializer relations - Django REST framework

relations.py Data structures, not algorithms, are central to programming. — Rob Pike Relational fields are used to represent model relationships. They can be applied to ForeignKey, ManyToManyField and OneToOneField relationships, as well as to reverse re

www.django-rest-framework.org

 

지금까지 했던 프로그램에서 예를 들면 다음과 같습니다.

 

먼저 models.py에서 지정한 related_name을 확인합니다.

 

# 해당 앱/models.py

from django.db import models


class StreamPlatform(models.Model):
    # Model(=DB)에서 사용할 Column 정의
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=50)
    about = models.TextField(max_length=200)
    website = models.URLField(max_length=100)

    def __str__(self):
        return self.name


class Movie(models.Model):
    # Model(=DB)에서 사용할 Column 정의
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=50)
    description = models.TextField(max_length=200)
    # StreamPlatform은 여러 개의 Movie를 가질 수 있음
    platform = models.ForeignKey(StreamPlatform, on_delete=models.CASCADE, related_name='movielist')
    active = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

 

위 코드에서 Movie Model에서 StreamPlatform과 연결한 이름(related_name)을 찾습니다.

 

이를 serializers.py에서 활용합니다.

 

from rest_framework import serializers
from watchlist_app.models import Movie, StreamPlatform
        
class MovieSerializer(serializers.ModelSerializer):
    len_name = serializers.SerializerMethodField()
    
    class Meta:
        model = Movie
        # 모든 Field를 사용하게 한다.
        fields = "__all__"
        # 사용하고 싶은 Field를 지정하고 싶으면 다음과 같이 한다
        # fields = ['id', 'name', 'description']
        
        # 또는 특정 Field만 제외하고싶다면 다음과 같이 한다.
        # exclude = ['activity']
        
    def get_len_name(self, object):
        return len(object.name)
        
    def validate(self, data):
        if data['name'] == data['description']:
            raise serializers.ValidationError("이름과 내용이 같아선 안됩니다.")
        else:
            return data
    
    # field level validation
    # validate_필드 이름으로 만들면 자동으로 오버라이드 해준다.
    def validate_name(self, value):
        if len(value) < 2:
        	raise serializers.ValidationError("이름이 너무 짧습니다.")
        else :
            return value
        
class StreamPlatfromSerializer(serializers.ModelSerializer):
	# related_name에서 정의한 이름과 똑같은 이름으로 변수를 정의한다.
    movielist = MovieSerializer(many=True, read_only=True)
    
    class Meta:
        model = StreamPlatform
        fields = "__all__"

 

여기까지 하고 Build 해보면 다음과 같은 결과를 볼 수 있다.

 

 

StreamPlatform Model 안에 movielist 항목이 생긴 것을 알 수 있다.

 

각각의 스트리밍 플랫폼이 어떤 movie를 갖고 있는지 확인할 수 있다.

 

반응형


"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


댓글