[Django/DB] Serializer 활용

문지은·2023년 5월 14일
0

Django + Database

목록 보기
12/12
post-thumbnail

여러가지 Serializer 활용 방법에 대해 알아보자.

특정 Article에서의 모든 댓글 조회하기

현재 API

시리즈를 잘 따라왔다면 현재 API가 다음과 같이 구성되었을 것이다.

  • 게시글(article) 관련

  • 댓글(comment) 관련

이렇게는 전체 댓글 조회밖에 하지 못하는데, 게시글당 댓글 조회를 할 수 있도록 수정해보자.

url 수정

# 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),
]

veiw 수정

  • comment_list와 comment_create 합치기
# 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)
  • GET 응답 결과
    • 이제 게시글 당 댓글을 볼 수 있다.

필드명 수정하기

  • 역참조명으로 설정되어 있는 필드명을 수정하기 위해서는 models.py에서 related_name을 통해 역참조명을 직접 변경하면 된다. (이전 글에서 알아보았음)
    • 하지만 이미 모델을 migrate 한 이후에는 migrate를 다시해야하고,
    • 이후에 view나 serializer에서 사용했던 역참조명을 전부 바꿔주어야 한다는 번거로움이 있다.
  • 이럴 때 to_representation()을 사용하면 된다!
    • comment_set → comments로 변경
# 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
  • 응답 결과

필요 없는 필드 삭제하기

  • 댓글 조회시 article id 삭제하기
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)
  • 적용 전

  • 적용 후

profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

0개의 댓글