AI웹 개발자 과정 공부 (팀스파르타)/Django (장고)

24.05.05_TIL (Django 심화 : Serializer 활용 )

티아(tia) 2024. 5. 30. 16:48
728x90

 

 

 

 

++ 장고 공식 문서는 항상 확인하기 

https://docs.djangoproject.com/en/4.2/

 

++ 과제 API 를 정해주어서 수정하여 진행

필수 기능 - MVP(Minimum Viable Product)

  • 회원가입
    • Endpoint: /api/accounts
    • Method: POST
    • 조건: username, 비밀번호, 이메일, 이름, 닉네임, 생일 필수 입력하며 성별, 자기소개 생략 가능
    • 검증: username과 이메일은 유일해야 하며, 이메일 중복 검증(선택 기능).
    • 구현: 데이터 검증 후 저장.
  • 로그인
    • Endpoint: /api/accounts/login
    • Method: POST
    • 조건: 사용자명과 비밀번호 입력 필요.
    • 검증: 사용자명과 비밀번호가 데이터베이스의 기록과 일치해야 함.
    • 구현: 성공적인 로그인 시 토큰을 발급하고, 실패 시 적절한 에러 메시지를 반환.
  • 프로필 조회
    • Endpoint: /api/accounts/<str:username>
    • Method: GET
    • 조건: 로그인 상태 필요.
    • 검증: 로그인 한 사용자만 프로필 조회 가능
    • 구현: 로그인한 사용자의 정보를 JSON 형태로 반환.

 

 

 

 

 

 

 

 

 

1.  게시글 목록과 댓글 목록을 같은 화면에 나오게 해보자

  • Article에 Comment 추가하기
  • Nested Relationships
    • Serializer는 기존 필드를 override 하거나 추가적인 필드를 구성할 수 있으며
    • 이때 모델 사이에 참조 관계가 있다면 해당 필드를 포함하거나 중첩할 수 있습니다.
  • 결국 우리가 조작해줘야할 것은~~ Serializer!
    • 현재 Article → Comments 접근이 필요 == 역참조
    • 역참조시 사용할 수 있는 comment_set 이 있으나 우리는 comments 로 명명합시다.

 

  • articles 의 serializers.py를 바꾸어준다. Comment가 속해야 하기 때문에 먼저 정의되어야 속할 수 있기에 순서를 먼저 바꾸어준다.
from rest_framework import serializers
from .models import Article, Comment


class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = "__all__"
        read_only_fields = ("article",)


class ArticleSerializer(serializers.ModelSerializer):
    comments = CommentSerializer(many=True, read_only=True)

    class Meta:
        model = Article
        fields = "__all__"

 

 

 

2번글을 상세조회해보면 안에 코멘트가 속해있는 것을 볼 수 있다.

 

 

 

 

 

 

 

 

 

 

2.  댓글 수가 나올 수 있게 하자.

 

  • articles 의 serializers.py를 바꾸어준다.
class ArticleSerializer(serializers.ModelSerializer):
    comments = CommentSerializer(many=True, read_only=True)
    comments_count = serializers.IntegerField(source="comments.count", read_only=True)

    class Meta:
        model = Article
        fields = "__all__"

 

 

 

 

 

 

 

 

 

 

 

3.  댓글에 보이는 articles : 2 를 없애보자.

  • 모델필드나 serializer 필드는 변경하지 않고 딱 보여지는 부분만 변경
  • articles 의 serializers.py를 바꾸어준다.
class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = "__all__"
        read_only_fields = ("article",)

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        ret.pop("article")
        return ret

 

공식문서에는 모든 해답이 있습니다! https://www.django-rest-framework.org/api-guide/fields/#custom-fields

 

 

 

 

 

 

 

 

 

 

4.  댓글을 목록에서가 아니라 상세에서만 보이게 해주자.

  • articles 의 serializers.py를 바꾸어준다. 
  • ArticleSerializer를 두개로 쪼개서 사용해주면 된다.
from rest_framework import serializers
from .models import Article, Comment

...

class ArticleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Article
        fields = "__all__"


class ArticleDetailSerializer(ArticleSerializer):
    comments = CommentSerializer(many=True, read_only=True)
    comments_count = serializers.IntegerField(source="comments.count", read_only=True)

 

 

  • articles 의 views.py 에서 Detail 부분을 ArticleDetailSerializer 로 바꾸어준다.
from .serializers import ArticleSerializer, ArticleDetailSerializer, CommentSerializer

...

class ArticleDetailAPIView(APIView):

    def get_object(self, pk):
        return get_object_or_404(Article, pk=pk)

    def get(self, request, pk):
        article = self.get_object(pk)
        serializer = ArticleDetailSerializer(article)
        return Response(serializer.data)

    def put(self, request, pk):
        article = self.get_object(pk)
        serializer = ArticleDetailSerializer(article, data=request.data, partial=True)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data)

    def delete(self, request, pk):
        article = self.get_object(pk)
        article.delete()
        data = {"pk": f"{pk} is deleted."}
        return Response(data, status=status.HTTP_200_OK)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형