N:1 관계에서의 모델 data를 Serialization 하여 JSON으로 변환하는 방법에 대해 알아보자.
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
$ python manage.py loaddata articles.json comments.json
# articles/serializers.py
from .models import Article, Comment
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
# articles/urls.py
urlpatterns = [
...,
path('comments/', views.comment_list),
]
# articles/views.py
from .models import Article, Comment
from .serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
@api_view(['GET'])
def comment_list(request):
comments = Comment.objects.all()
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
# articles/urls.py
urlpatterns = [
...,
path('comments/<int:comment_pk>/', views.comment_detail),
]
# articles/views.py
@api_view(['GET'])
def comment_detail(request, comment_pk):
if request.method == 'GET':
comment = Comment.objects.get(pk=comment_pk)
serializer = CommentSerializer(comment)
return Response(serializer.data)
# articles/urls.py
urlpatterns = [
...,
path('articles/<int:article_pk>/comments/', views.comment_create),
]
# articles/views.py
@api_view(['POST'])
def comment_create(request, article_pk):
article = Article.objects.get(pk=article_pk)
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(article=article)
return Response(serializer.data, status=status.HTTP_201_CREATED)
.save()
read_only_fields
를 사용해 외래 키 필드를 ‘읽기 전용 필드’
로 설정# articles/serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('article', )
# articles/views.py
@api_view(['GET', 'DELETE', 'PUT'])
def comment_detail(request, comment_pk):
comment = Comment.objects.get(pk=comment_pk)
if request.method == 'GET':
serializer = CommentSerializer(comment)
return Response(serializer.data)
elif request.method == 'DELETE':
comment.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
@api_view(['GET', 'DELETE', 'PUT'])
def comment_detail(request, comment_pk):
comment = Comment.objects.get(pk=comment_pk)
if request.method == 'GET':
serializer = CommentSerializer(comment)
return Response(serializer.data)
elif request.method == 'DELETE':
comment.delete()
data = {
'delete': f'댓글 {comment_pk}번이 삭제되었습니다.',
}
return Response(data, status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
# articles/serializers.py
class ArticleSerializer(serializers.ModelSerializer):
# 역참조 데이터 조회
comment_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Article
fields = '__all__'
related_name
을 통해 이름 변경 가능comment_set
을 override 할 수 있음# articles/models.py
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments')
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
# articles/serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('article', )
class ArticleSerializer(serializers.ModelSerializer):
comment_set = CommentSerializer(many=True, read_only=True)
class Meta:
model = Article
fields = '__all__'
# articles/serializers.py
class ArticleSerializer(serializers.ModelSerializer):
comment_set = CommentSerializer(many=True, read_only=True)
comment_count = serializers.IntegerField(source='comment_set.count', read_only=True)
class Meta:
model = Article
fields = '__all__'
# 사용 불가능
class ArticleSerializer(serializers.ModelSerializer):
comment_set = CommentSerializer(many=True)
comment_count = serializers.IntegerField(source='comment_set.count')
class Meta:
model = Article
fields = '__all__'