이전 포스팅에서 Nested Relationships에 대해 알아봤습니다.
https://android-developer.tistory.com/86
Nested Relationships는 다른 Model의 데이터를 참조하는 것이였는데요.
만약 해당 Model의 특정 부분의 정보만 갖고 싶다면 어떻게해야할까요?
Serializer relations을 사용하면 해당 Model의 특정 부분만 가져올 수 있습니다.
이번 포스팅에선 Serializer relations의 모든 API를 알아보는 것이 아니라 자주 사용하는 일부 API에 대해 알아보겠습니다.
- StringRelatedField
- PrimaryKeyRelatedField
- HyperlinkedRelatedField
StringRelatedField
해당 Model의 __str__ 의 반환값을 얻어올 수 있습니다.
예를 들면 models.py에서 다음과 같은 __str__ 함수를 확인할 수 있습니다.
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
간단하게 기존에 있던 MovieSerializer를 StringRelatedField로 바꾸는 것만으로도 사용할 수 있다.
변경전에는 movielist 전체가 출력되지만
다음과 같이 코드를 변경하면
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)
# StringRelatedField 사용
movielist = serializers.StringRelatedField(many=True)
class Meta:
model = StreamPlatform
fields = "__all__"
다음과 같이 movie의 title만 출력되는 것을 알 수 있다. (title이 출력되는 이유는 __str__에서 name을 출력하도록 했기 때문)
참고로 현재 Movie 모델은 다음과 같다.
PrimaryKeyRelatedField
위에서 StringRelatedField를 사용하여 __str__의 결과를 얻어올 수 있었다.
PrimaryKeyRelatedField를 사용하면 각 아이템의 key 값을 얻어올 수 있다.
StringRelatedField를 PrimaryKeyRelatedField로 바꿔주면된다.
class StreamPlatfromSerializer(serializers.ModelSerializer):
# related_name에서 정의한 이름과 똑같은 이름으로 변수를 정의한다.
# movielist = MovieSerializer(many=True, read_only=True)
# PrimaryKeyRelatedField 사용
movielist = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = StreamPlatform
fields = "__all__"
HyperlinkedRelatedField
사실 Movie 모델에는 해당 Movie의 위치가 담긴 url이 존재한다.
그렇다면 해당 url만 얻고싶을 때는 어떻게 할까?
HyperlinkedRelatedField를 사용하면 간단하게 url만 얻을 수 있다.
다음과 같이 바꿔준다.
class StreamPlatfromSerializer(serializers.ModelSerializer):
# related_name에서 정의한 이름과 똑같은 이름으로 변수를 정의한다.
# movielist = MovieSerializer(many=True, read_only=True)
# StringRelatedField 사용
movielist = serializers.HyperlinkedRelatedField(
many=True,
read_only=True,
view_name='movie-detail' # urls.py에서 지정한 name으로 설정
)
class Meta:
model = StreamPlatform
fields = "__all__"
참고로 view_name은 urls.py에서 정의한 name을 사용한다.
결과는 다음과 같이 나온다.
그럼 다음과 같은 에러가 발생하는 것을 볼 수 있다.
말 그대로 HyperlinkedRelatedField는 context가 필요하다는 뜻이다.
views.py 부분에 다음과 같이 context를 넘겨주도록 변경한다.
# api/views.py
class StreamPlatformAV(APIView):
def get(self, request):
platform = StreamPlatform.objects.all()
serializer = StreamPlatfromSerializer(platform, many=True, context={'request': request})
return Response(serializer.data)
def post(self, request):
serializer = StreamPlatfromSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors)
그리고 다시 프로젝트를 실행하면 다음과 같은 화면을 얻을 수 있다.
그리고 해당 url로 이동해보면 다음과 같은 화면을 얻을 수 있다.
'파이썬(Python) > 장고(Django)' 카테고리의 다른 글
[기초] 파이썬 장고 REST API - Nested Relationships (0) | 2024.02.15 |
---|---|
[기초] 파이썬 장고 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 |
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
댓글