11월 16일 원티드 프리온보딩 백엔드 21일차 TIL

DRF Pagination

1️⃣ 진행상황

  • Serializer, View 생성 및 URL 연결

2️⃣ 진행상황리뷰

# audio/utils/audio_converter.py
...
class ProjectCreateSerializer(serializers.ModelSerializer):
    ...
    def create(self, validated_data: dict[str, str]):
        title = validated_data.get("project_title")
        project = Project.objects.create(project_title=title)
        text = validated_data.get("text")
        sentences = separate_text_by_sentence(text)
        for index, sentence_text in enumerate(sentences):
            sentence, is_created = Sentence.objects.get_or_create(text=sentence_text)
            if is_created:
                create_audio_file(sentence_text)
            Audio.objects.create(
                project_id=project,
                index=index,
                sentence=sentence,
            )
        return project


class AudioSerializer(serializers.ModelSerializer):
    ...
    def update(self, instance, validated_data):
        instance.speed = validated_data.get("speed")
        if instance.text != validated_data.get("text"):
            sentence, is_created = Sentence.objects.get_or_create(
                text=validated_data.get("text")
            )
            instance.sentences = sentence
            if is_created:
                create_audio_file(validated_data.get("text"), speed=instance.speed)
        instance.save()
        return instance
  • ProjectCreateSerializerProject를 생성할 때, text를 받아서 문장 단위로 분리하고, Sentence가 존재하는지 확인하고, 존재하지 않는다면 create_audio_file을 통해 음성 파일을 생성. 이후 생성한 SentenceProject를 연결하여 Audio를 생성.
  • AudioSerializerAudio를 수정할 때, text가 변경되었다면 Sentence를 생성하고, create_audio_file을 통해 음성 파일을 생성. 이후 Audiospeed를 변경하고 저장.
# audio/views.py
from rest_framework.pagination import PageNumberPagination
...
class AudioPagination(PageNumberPagination):
    page_size = 10
...
class ProjectView(APIView):
    def get(self, request: Request, project_pk: int) -> Response:
        """
        GET /api/v1/project/<project_pk>/
        Get project from pk.
        """
        project = get_object_or_404(Project, pk=project_pk)
        audio = project.audio_set.all().order_by("index")
        # paginate
        paginator = AudioPagination()
        result_page = paginator.paginate_queryset(audio, request)
        return paginator.get_paginated_response(
            AudioSerializer(result_page, many=True).data
        )
  • AudioPagination을 통해 page_size를 10으로 설정.
  • Projectpk를 받아서 Audioindex 순으로 정렬하여 반환하는 ProjectView를 생성.

3️⃣ Today I Learned

Pagination

데이터를 여러 페이지에 나눠 보여주는 기능이다.
DRF에서는 rest_framework.pagination에서 제공하는 PageNumberPagination을 그대로 사용하거나, 상속받아 원하는 대로 변경하여 사용할 수 있다.
config.settings.py에서 DEFAULT_PAGINATION_CLASS를 설정하여 전역으로 사용할 수 있다.

# config.settings.py
...
REST_FRAMEWORK = {
    ...
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
}

ViewSet에서 pagination_class를 설정하여 해당 ViewSet에서만 사용할 수 있다.

# audio/views.py
...
class AudioViewSet(viewsets.ModelViewSet):
    ...
    pagination_class = AudioPagination

APIView에서는 좀더 설정이 필요하다.
APIView에서 pagination_class를 설정하고, paginate_queryset를 통해 querysetpaginator에 넘겨주고, get_paginated_response를 통해 Response를 반환한다.
내 경우는 커스텀이 필요해서 다음과 같은 방식을 사용했다.

# audio/views.py
...
class ProjectView(APIView):
    def get(self, request: Request, project_pk: int) -> Response:
        ...
        paginator = AudioPagination()
        result_page = paginator.paginate_queryset(audio, request)
        return paginator.get_paginated_response(
            AudioSerializer(result_page, many=True).data
        )

© 2021. All rights reserved.

Powered by Hydejack v7.5.2