[DRF] 클래스형 뷰와 시리얼라이저

집중맞은 도둑력·2024년 4월 23일

웹 개발

목록 보기
10/14
post-thumbnail

0. 🔖 목차


  1. 기초
    1-1. 클래스형 뷰
    1-2. 시리얼라이즈

1. 기초


1-1. 클래스형 뷰

장고의 클래스형 뷰를 사용하면 뷰의 기능을 객체 지향 방식으로 구현할 수 있다.

클래스형 뷰를 사용하면 코드의 재사용성을 높이고, 코드를 체계적으로 관리할 수 있다.

class AricleListAPIView(APIView):
    def get(self, request):
        pass

    def post(self, request):
        pass

클래스 뷰를 사용하려면 위 코드처럼 클래스를 선언하고 APIView를 상속받는다.

이후 이 클래스 뷰에서 처리하고자 하는 요청 메소드를 함수로 정의하면 된다.

클래스 뷰에서 정의되지 않은 메소드는 자동으로 Bad Request로 처리된다.

상속받을 클래스 뷰로는 APIView 말고도 여러가지가 존재한다.

1-2. 시리얼라이저

이전에는 모델 시리얼라이저를 통해 모델 필드에 맞춰서 쿼리셋을 JSON으로 변환해주는 직렬화 클래스를 정의해주었다.

이번에는 이러한 시리얼라이즈를 다양하게 커스텀할 수 있는 방법을 정리했다.

필드 표현

만약 시리얼라이저로 쿼리셋을 JSON 데이터로 변환한 뒤 반환하기 전에 특정 데이터에 대해서 연산을 하고 싶다면 to_representation 메소드를 오버라이딩하면 된다.

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = '__all__'
        # article은 읽기에서만 is_valid에서 검사를 할 것
        read_only_fields = ("article",)

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

위 코드는 전체 데이터중 article 키만을 빼고 반환해주는 코드이다.

코드에서 보이듯 super().to_representation(instance)를 통해 딕셔너리로 결과를 받으면 이후에 원하는대로 데이터를 조작하면 된다.

커스텀 메소드

복잡한 데이터를 처리할 때 커스텀 메소드를 정의할 수 있다.

days_since_created = serializers.SerializerMethodField()

def get_days_since_created(self, obj):
    return (timezone.now() - obj.created).days

위처럼 시리얼라이저 내부에 days_since_created 변수를 선언하여 반환할 JSON 데이터에 days_since_created 필드를 추가하고 serializers.SerializerMethodField()로 초기화한다.

이후에는 get_<정의한 필드 이름> 메소드를 정의하여 해당 필드에 저장될 값이 어떠한 로직을 통해서 저장될 것인지 작성하면 된다.

참고로 커스텀 메소드는 읽기 전용이 기본값이다.

필드 옵션

위처럼 특정 필드를 읽기 전용으로 설정하여 API 요청에서 해당 필드를 수정하지 못하도록 할 수 있다.

comments_count = serializers.IntegerField(source="comments.count", read_only=True)

아티클 내부의 댓글 개수를 나타내는 필드를 시리얼라이저에서 새로 정의한다고 했을 때 만약 POST 요청에서 해당 필드를 수정할 수 있으면 안된다.

때문에 위 코드처럼 read_only=True를 하여 읽기에서만 해당 JSON 데이터가 나오도록 만들 수 있다.

유효성 검사

모델 폼처럼 데이터를 저장하기 전에 필드에 저장될 값이 저장되기 전 유효성 검사를 진행할 수 있다

def validate_title(self, value):
    if 'Django' not in value:
        raise serializers.ValidationError("Title must include 'Django'")
    return value

validate_<정의한 필드 이름> 메소드를 정의하여 안에 유효성 검사 로직을 작성하면 된다.

상속

시리얼라이즈를 상속받아서 추가적인 데이터를 전달할 수 있다.

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)
    days_since_created = serializers.SerializerMethodField()

    def get_days_since_created(self, obj):
        return (now() - obj.created_at).days

ArticleSerializer를 사용하면 Article 모델에 정의된 필드의 값이 JSON으로 반환되고

ArticleDetailSerializer를 사용하면 comments, comments_count, days_since_created 필드가 추가적으로 반환된다.

profile
틀린_내용이_있다면_말해주세요.

0개의 댓글