SW Engineer & Developer/Python Craft

React REST Framework 제네릭 뷰 검색 조건

ByteCraft 2025. 1. 28. 23:27
제너릭 뷰 ListCreateAPIView
코드구분, 코드구분명으로 검색 조건 설정

 

변경전
class CodeDevList(ListCreateAPIView):
    queryset = CodeDiv.objects.all()
    serializer_class = CodeDivSerializer

    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')
        if cd_div and cd_div_nm:
            queryset = queryset.filter(cd_div__icontains=cd_div, cd_div_nm__icontains=cd_div_nm)
        if cd_div:
            queryset = queryset.filter(cd_div__icontains=cd_div)
        if cd_div_nm:
            queryset = queryset.filter(cd_div_nm__icontains=cd_div_nm)
        return queryset

 

변경후
class CodeDevList(ListCreateAPIView):
    queryset = CodeDiv.objects.all()
    serializer_class = CodeDivSerializer

    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)

 

 

참고자료 : queryset.filter
queryset.filter는 Django ORM에서 사용되는 메서드로, 데이터베이스 쿼리를 수행하여 특정 조건을 만족하는 객체들의 **하위 집합(subset)**을 반환하는 데 사용됩니다. 이 메서드는 원본 QuerySet을 수정하지 않고 새롭게 필터링된 QuerySet을 반환합니다.

기본 사용법

filtered_queryset = MyModel.objects.filter(조건1, 조건2, ...)
  • 조건: 필터링 조건은 키워드 인수로 전달됩니다. 조건은 모델 필드명Lookup Expressions(조회 표현식)을 조합하여 정의합니다.

주요 특징

  1. Lazy Evaluation (지연 평가)
    • filter는 즉시 데이터베이스에서 데이터를 가져오는 것이 아니라, 쿼리 생성만 합니다.
    • 실제 데이터베이스 요청은 쿼리 결과를 사용하려 할 때(예: .all(), .first() 호출 등) 발생합니다.
  2. 조건 조합
    • 조건을 쉼표(,)로 연결하면 AND 조건으로 처리됩니다.
    • Q 객체를 사용하면 AND/OR 논리 조합이 가능합니다.

Lookup Expressions(조회 표현식)

일치 조건

  • filter(field=value)
    필드 값이 value와 정확히 일치하는 객체를 반환합니다.
MyModel.objects.filter(name="John")

비교 연산

  • __lt (less than): 미만
  • __lte (less than or equal): 이하
  • __gt (greater than): 초과
  • __gte (greater than or equal): 이상
MyModel.objects.filter(age__gte=30)  # age >= 30

 

부분 문자열 검색

  • __contains: 대소문자 구분 포함 여부
  • __icontains: 대소문자 구분 없이 포함 여부
MyModel.objects.filter(description__icontains="Python")

 

NULL 여부

  • __isnull: NULL 값인지 여부를 확인
MyModel.objects.filter(email__isnull=True)

 

범위 검색

  • __range: 특정 범위 내에 속하는지 확인
MyModel.objects.filter(age__range=(20, 30))  # age BETWEEN 20 AND 30

 

날짜 관련

  • __year, __month, __day 등
MyModel.objects.filter(created_at__year=2025)

 

다대다 관계

  • 다대다 필드에서 필터링 가능
MyModel.objects.filter(tags__name="Django")

AND/OR 논리 조합

AND 조건 (기본 동작)

MyModel.objects.filter(name="John", age=30)

OR 조건

Q 객체를 사용

from django.db.models import Q

MyModel.objects.filter(Q(name="John") | Q(age=30))

체이닝

filter는 여러 번 체이닝 가능하며, 각각의 filter는 이전 조건 위에 추가 조건을 더합니다.

MyModel.objects.filter(status="active").filter(age__gte=25)

결과

filter는 항상 QuerySet을 반환하므로, 추가적으로 데이터를 가져오거나 수정하는 메서드를 사용할 수 있습니다.

  • .all(): 모든 객체 가져오기
  • .first(): 첫 번째 객체 가져오기
  • .count(): 객체 수 세기
  • .exists(): 조건에 맞는 객체 존재 여부 확인

예시

# 특정 이름을 가진 사용자 중, 20~30세인 사람 찾기
users = User.objects.filter(name="John", age__range=(20, 30))

# 상태가 'active'이거나 이메일이 NULL인 사용자 찾기
users = User.objects.filter(Q(status="active") | Q(email__isnull=True))

# 쿼리 확인
print(users.query)

이처럼 filter는 조건에 맞는 데이터를 효율적으로 가져오도록 돕는 핵심 메서드입니다.

 

 

참고자료 : Q 객체
Q 객체는 Django에서 복잡한 쿼리 조건을 조합할 때 사용되는 객체입니다. Q 객체를 사용하면 조건들을 논리적으로 결합할 수 있으며, AND, OR 등의 연산을 적용할 수 있습니다.

 

코드 설명

from django.db.models import Q

filters = Q()  # 빈 Q 객체를 생성합니다.
  • Q() 객체를 빈 상태로 초기화합니다. Q()는 쿼리 조건을 나타내는 객체로, 나중에 필터 조건을 조합하기 위해 사용됩니다.
if cd_div:
    filters &= Q(cd_div__icontains=cd_div)
  • cd_div 값이 존재하는 경우, Q(cd_div__icontains=cd_div) 조건을 filters 객체에 추가합니다.
  • &= 연산자는 논리적인 AND를 의미합니다. 즉, 이전에 설정된 조건(filters)과 새로 추가한 조건을 결합합니다.
  • cd_div__icontains=cd_div는 cd_div 필드에 대해 대소문자를 구분하지 않고 포함하는 값을 찾는 조건입니다.
if cd_div_nm:
    filters &= Q(cd_div_nm__icontains=cd_div_nm)
  • cd_div_nm 값이 존재하면, Q(cd_div_nm__icontains=cd_div_nm) 조건을 filters 객체에 추가합니다.
  • 이 역시 &= 연산자를 사용해 이전의 filters와 결합하여 두 조건을 모두 만족하는 쿼리가 생성됩니다.

최종적으로 filters는 여러 조건이 결합된 Q 객체입니다.

return queryset.filter(filters)
  • filters가 최종적으로 적용된 필터 조건이 되어, queryset.filter(filters)로 실제 데이터베이스에 쿼리를 실행합니다. filters에 포함된 조건을 만족하는 데이터를 반환하게 됩니다.

요약

Q 객체를 사용하면 여러 조건을 동적으로 조합할 수 있습니다. &= 연산자를 사용하여 조건을 추가하고, 마지막에 queryset.filter(filters)로 조건을 한 번에 적용할 수 있습니다. 이렇게 하면 조건이 많을 때 코드가 간결하고 효율적으로 작성됩니다.

 

검색조건 추가 후 테스트

 

[1. 전체. 검색조건 없음]

 

[2.검색조건 하나]
[3. 검색조건 두개]