SW Engineer & Developer/Python Craft

(Pythen/Django REST) ListCreateAPIView에서 Sort 적용

ByteCraft 2025. 2. 2. 23:31

 

개요

ListCreateAPIView는 Django REST framework에서 제공하는 제네릭 뷰 중 하나로, 목록 조회 및 객체 생성을 처리합니다.

이 뷰에 대한 sort 기능을 정의하는 방법은 일반적으로 ordering 쿼리 매개변수를 사용하여 데이터를 정렬하는 방식입니다.

Serializer에서 Meta 클래스를 사용하여 기본 ordering 설정

모델이 정의되어 있고, ModelViewSet을 사용할 경우 ordering을 Meta 클래스에 설정할 수 있습니다.

from rest_framework import serializers
from .models import MyModel

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'
        ordering = ['field_name']  # 기본 정렬 필드 지정
APIView에서 ordering 쿼리 매개변수 처리

ListCreateAPIView를 사용하여 get_queryset에서 정렬을 처리할 수 있습니다.

from rest_framework.generics import ListCreateAPIView
from rest_framework import permissions
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelListCreateAPIView(ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        queryset = MyModel.objects.all()
        ordering = self.request.query_params.get('ordering', None)
        if ordering:
            queryset = queryset.order_by(ordering)
        return queryset

 

OrderingFilter를 사용하여 자동으로 정렬 기능 추가

Django REST framework는 OrderingFilter를 제공하여 쿼리 매개변수로 정렬을 쉽게 추가할 수 있습니다.

OrderingFilter를 사용하려면 뷰셋에 필터 클래스를 추가합니다.

from rest_framework.filters import OrderingFilter
from rest_framework.generics import ListCreateAPIView
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelListCreateAPIView(ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ['field_name1', 'field_name2']  # 정렬 가능한 필드 정의

이렇게 하면 ordering 쿼리 매개변수에 맞춰 자동으로 정렬됩니다. 예를 들어:

GET /api/mymodel/?ordering=field_name1

 

결론 및 요약

"OrderingFilter를 사용하여 자동으로 정렬 기능 추가" 방식을 적용 하기로 함.

from rest_framework.filters import OrderingFilter # ordering 기능을 활성화

class CodeDevList(ListCreateAPIView):
    queryset = CodeDiv.objects.all()
    serializer_class = CodeDivSerializer
    
    # ordering 기능을 활성화하기 위해 OrderingFilter가 필요
    filter_backends = [OrderingFilter]                     
    ordering_fields = ['cd_div', 'cd_div_nm', 'sort_key']  # 정렬 가능한 필드 정의
    ordering = ['cd_div']                                  # 기본 정렬 기준

    def get_queryset(self):
        queryset = super().get_queryset()
        cd_div = self.request.query_params.get('cd_div')
        cd_div_nm = self.request.query_params.get('cd_div_nm')


        filters = Q()
        if cd_div:
            filters &= Q(cd_div__icontains=cd_div)
        if cd_div_nm:
            filters &= Q(cd_div_nm__icontains=cd_div_nm)
        return queryset.filter(filters)
검색조건 : cd_div, cd_div_nm
정열조건 : cd_div, cd_div_nm, sort_key
Test URL
http://127.0.0.1:8000/code_div_list?cd_div=&ordering=sort_key
http://127.0.0.1:8000/code_div_list?cd_div=adm&ordering=-sort_key
🥨Sort Desc(내림차순) 정열을 하려면, 대상 컬럼 앞에 "-"를 추가.

 

React에서 Django REST Call
//api.js
export async function getCodeDiv({qCodeDiv = "", qCodeDivNm = "", order = ""}) {
  const query = `cd_div=${qCodeDiv}&cd_div_nm=${qCodeDivNm}&ordering=${order}`;
  console.log("query",query);
  const response = await fetch(`http://127.0.0.1:8000/code_div_list?${query}`);
  const body = await response.json();
  return body;
}
//Ezpo.js
import { useEffect, useState } from "react";
import { getCodeDiv } from "../api";
import EzpoCodeDivList from "./EzpoCodeDivList";

function Ezpo() {
  const [codeDiv, setCodeDiv] = useState([]);
  const [qCodeDiv, setQCodeDiv] = useState("ADM"); //검색조건
  const [qCodeDivNm, setQCodeDivNm] = useState("");
  const [order, setOrder] = useState("sort_key"); //정열조건
  const [isLoading, setIsLoading] = useState(false);
  const [loadingError, setLoadingError] = useState(null);

  
  const handleLoadCodeDiv = async (options) => {
    let result;
    try {
      setIsLoading(true);
      setLoadingError(null);
      result = await getCodeDiv(options);
      console.log("options",options);
    } catch (error) {
      setLoadingError(error);
      return;
    } finally {
      setIsLoading(false);
    }
    setCodeDiv(result);
  };

  useEffect(() => {
    handleLoadCodeDiv({qCodeDiv, qCodeDivNm, order});
  }, []);

  return (
    <div>
      <h1>EZPO</h1>
      <EzpoCodeDivList items={codeDiv} />
    </div>
  );
}
export default Ezpo;

'SW Engineer & Developer > Python Craft' 카테고리의 다른 글

Django MariaDB AutoCommit  (0) 2025.01.29
React REST Framework 제네릭 뷰 검색 조건  (0) 2025.01.28