이전 포스팅에서 Relationships에 대해 알아봤습니다.
https://android-developer.tistory.com/85
이번에는 다수의 Model을 연결하는 Nested Relationships에 대해 알아보겠습니다.
- Relationships를 사용하여 특정 아이템을 서로 묶기
- Nested Relationships 사용하기
Relationships를 사용하여 특정 아이템을 서로 묶기
이전 포스팅에서 저희는 기존에 있는 Movies라는 Model 이외에 StreamPlatform이라는 Model을 새롭게 만들었습니다.
Nested Relationships를 적용하기 전에 Movies 와 StreamPlatform 사이에 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에 들어가서 아이템을 추가해보면
사진과 같이 Platform 부분이 생성된 것을 알 수 있습니다.
해당 Platform에서 다음과 같이 생성해놓은 Platform을 선택할 수 있게됩니다.
Platform을 선택하면 다음과 같이 Movies 아이템에서 Platform의 id로 값이 표시되어있는 것을 알 수 있습니다.
Nested Relationships 사용하기
지금까지의 과정으로 Movie와 StreamPlatform이라는 2개의 model을 생성했습니다.
이름에서 알 수 있다시피 StreamPlatform은 스트리밍 플랫폼이며 이는 많은 Movie를 가질 수 있음을 의미합니다.
즉, StreamPlatform Model은 Movie Model을 가질 수 있습니다.
이를 Nested Relationships라고 합니다.
공식 문서는 다음과 같습니다.
지금까지 했던 프로그램에서 예를 들면 다음과 같습니다.
먼저 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를 갖고 있는지 확인할 수 있다.
'파이썬(Python) > 장고(Django)' 카테고리의 다른 글
[기초] 파이썬 장고 REST API - Serializer relations (1) | 2024.02.18 |
---|---|
[기초] 파이썬 장고 REST API - Relationship 설정하기 (1) | 2024.02.05 |
[기초] 장고 REST API 프레임워크 - Model Serializer (0) | 2024.02.05 |
[기초] 파이썬 장고 REST API 프레임워크 - Validation (0) | 2024.02.02 |
[기초] 파이썬 장고 REST API 프레임 워크 - Class-based Views (0) | 2024.02.01 |
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
댓글