RelatedField
1. PrimaryKeyRelatedField
현재 User List를 살펴보면, 각 유저의 question 필드에 질문 레코드의 id값이 표시되는 것을 확인할 수 있다. 이것은 serializers.py에서 UserSerializer를 설정할 때 PrimaryKeyRelatedField를 사용했기 때문이다.
# mysite/polls_api/serializers.py
class UserSerializer(serializers.ModelSerializer):
# questions 필드를 명시하는 이유: User 모델과 Question 모델 간의 관계를 보여주기 위함
questions = serializers.PrimaryKeyRelatedField(many=True, queryset=Question.objects.all())
PK-FK 관계로 이어진 값을 나타내기 때문에, 해당 필드에 id값이 표시되는 것이다.
2. StringRelatedField
id값이 아닌 __str__() 함수에 의해 표시되는 문자열로 표시하게 할 수도 있다.
# User 모델과 Question 모델 간의 관계를 보여주는 Serializer
class UserSerializer(serializers.ModelSerializer):
questions = serializers.StringRelatedField(many=True, read_only=True)
StringRelatedField를 사용하면 Model의 __str__() 함수로 표현되는 문자열로 표시된다.
3. SlugRelatedField
자식 모델이 가지고 있는 필드 중 원하는 필드를 하나 골라서 출력하는 방법도 있다.
class UserSerializer(serializers.ModelSerializer):
questions = serializers.SlugRelatedField(many=True, slug_field='pub_date', read_only=True)
Question 모델의 'pub_date' 필드를 출력하도록 했다. SlugRelatedField를 사용하면 이처럼 원하는 필드를 출력하게 만들 수 있다.
4. HyperlinkedRelatedField
해당 모델의 상세 페이지로 이동할 수 있는 하이퍼링크를 출력하게 할 수도 있다.
class UserSerializer(serializers.ModelSerializer):
questions = serializers.HyperlinkedRelatedField(many=True, view_name='question-detail', read_only=True)
HyperlinkedRelatedField를 사용하면 위처럼 하이퍼링크를 넣을 수 있다. view_name은 urls.py에서 지정한 name을 사용한다.
# 참고 urls.py
from django.urls import path, include
from .views import *
urlpatterns = [
path('question/', QuestionList.as_view(), name='question-list'),
path('question/<int:pk>/', QuestionDetail.as_view(), name='question-detail'),
...
]
Related_name 이용하기
모델에서 FK로 상속받는 필드에 related_name을 지정하면 상위 모델에서 그 이름으로 역참조를 할 수 있다는 것을 기억하는가? (User-Question 모델 사이 연결)
Choice 모델의 question 필드에도 related_name을 지정해 QuestionSerializer에서 사용할 수 있도록 하려고 한다.
mysite/polls/models.py
class Choice(models.Model):
# 어떤 질문에 대한 답인지 알아볼 수 있도록 Question 클래스에서 FK를 받아옴
question = models.ForeignKey(Question, related_name='choices', on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
# 답변의 빈도를 세기 위한 정수 필드
votes = models.IntegerField(default=0)
# 문자열을 표시할 때 question_text를 반환
def __str__(self):
return f'[{self.question.question_text}] {self.choice_text}'
choices 라는 이름으로 related_name을 지정해줬다.
이제 시리얼라이저에 choices가 표시되도록 설정해보자. 우선 ChoiceSerializer부터 생성한 뒤, 그 클래스를 사용해 choices를 QuestionSerializer에서 불러올 것이다.
class ChoiceSerializer(serializers.ModelSerializer):
class Meta:
model = Choice
fields = ['choice_text', 'votes']
# Question 모델을 보여주는 Serializer
class QuestionSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
choices = ChoiceSerializer(many=True, read_only=True)
class Meta:
model = Question
fields = ['id', 'question_text', 'pub_date', 'owner', 'choices']
위와 같이 코드를 수정한 뒤 Question_list를 다시 살펴보자.
위와 같이 해당 질문 레코드에 관계된 답변(choices)이 모두 출력되는 것을 볼 수 있다.
'Minding's Programming > Django' 카테고리의 다른 글
[Django] Testing(Testing Serializer, Testing View) (0) | 2024.10.12 |
---|---|
[Django] 투표 기능 구현하기 (0) | 2024.10.11 |
[Django] User 항목 모델에 추가 / User 관리 / User생성 / User 권한 (2) | 2024.10.10 |
[Django] 클래스 기반의 View, Mixin, Generic View (0) | 2024.10.10 |
[Django] GET, POST, PUT, DELETE (1) | 2024.10.10 |