여러가지 Serializer 활용 방법에 대해 알아보자.
시리즈를 잘 따라왔다면 현재 API가 다음과 같이 구성되었을 것이다.
이렇게는 전체 댓글 조회밖에 하지 못하는데, 게시글당 댓글 조회를 할 수 있도록 수정해보자.
# articles/views.py
from django.urls import path
from articles import views
urlpatterns = [
path('articles/', views.article_list),
path('articles/<int:article_pk>/', views.article_detail),
# path('comments/', views.comment_list),
path('comments/<int:comment_pk>/', views.comment_detail),
path('articles/<int:article_pk>/comments/', views.comment_list),
]
# articles/views.py
@api_view(['GET', 'POST'])
def comment_list(request, article_pk):
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'POST':
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)
elif request.method == 'GET':
comments = article.comment_set.all()
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
related_name
을 통해 역참조명을 직접 변경하면 된다. (이전 글에서 알아보았음)to_representation()
을 사용하면 된다!# 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__'
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['comments'] = rep.pop('comment_set', [])
return rep
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('article', )
def to_representation(self, instance):
rep = super().to_representation(instance)
rep.pop('article', None)
return rep
# articles/serializers.py
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content')
class ArticleDetailSerializer(ArticleListSerializer):
comment_set = CommentSerializer(many=True, read_only=True)
comment_count = serializers.IntegerField(source='comment_set.count', read_only=True)
class Meta(ArticleListSerializer.Meta):
fields = ArticleListSerializer.Meta.fields + (
'comment_set',
'comment_count',
)
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['comments'] = rep.pop('comment_set', [])
return rep
# articles/views.py
from .serializers import ArticleDetailSerializer
@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'GET':
serializer = ArticleDetailSerializer(article)
return Response(serializer.data)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleDetailSerializer(article, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)