drf ListAPIView에서 fk 실제 값 가져오기(ModelSerializer, SerializerMethodField)

yo·2021년 2월 9일
0

모델 상황

  1. 포인트 모델
class Point(BaseModel):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True
    )
    status = models.ForeignKey("PointStatus", verbose_name="상태", on_delete=models.SET_NULL, null=True)
    description = models.CharField(max_length=20, verbose_name="포인트 설명", blank=True)
    amount = models.IntegerField(verbose_name="금액")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="처리일자")
    end_at = models.DateField(verbose_name="포인트 만료일시", null=True)
  1. 포인트 상태 모델(적립, 사용, 만료)
class PointStatus(models.Model):
    name = models.CharField(max_length=14, verbose_name="포인트 상태")

위처럼 생긴 포인트 모델이 있다.

요구사항

ListAPIView를 사용하여 유저의 포인트 내역을 리턴하는 api를 만든다.

이를 위해 아래의 serializer를 만든다.

class PointRetrieveSerializer(serializers.ModelSerializer):
    """유저의 포인트 내역을 보여주는 뷰에 사용되는 serializer"""
    class Meta:
        model = models.PointEvent
        fields = ("user", "status", "description", "amount", "created_at", "end_at")

뷰는 다음과 같다.

class PointListAPIView(ListAPIView):
    serializer_class = serializers.PointRetrieveSerializer
    permission_classes = (permissions.IsUser, )

    def get_queryset(self):
        return models.PointEvent.objects.filter(user=self.request.user)

결과 값은 아래처럼 출력된다.

[
    {
        "user": 10,
        "status": 1,
        "description": "구매 확정으로 1% 적립",
        "amount": 15000,
        "created_at": "2021-02-09T11:00:58.347666+09:00",
        "end_at": "2023-02-09"
    },
]

문제는 fk인 status가 숫자로 출력되면서, 1이 뭔지 프론트에서 알 수 없다는 거다.
status의 pk가 아닌 내가 원하는 값을 출력하는게 이 포스팅의 목적이다.
이를 위해 SerializerMethodField를 활용해보자.

class PointRetrieveSerializer(serializers.ModelSerializer):
    """유저의 포인트 내역을 보여주는 뷰에 사용되는 serializer"""
    class Meta:
        model = models.PointEvent
        fields = ("user", "status_name", "description", "amount", "created_at", "end_at")

    status_name = serializers.SerializerMethodField('get_status_name')

    def get_status_name(self, obj):
        return obj.status.name

결과값이 "적립"으로 출력됨을 볼 수 있다.

[
    {
        "user": 10,
        "status_name": "적립",
        "description": "구매 확정으로 1% 적립",
        "amount": 15000,
        "created_at": "2021-02-09T11:00:58.347666+09:00",
        "end_at": "2023-02-09"
    },
]
profile
Never stop asking why

0개의 댓글