ABOUT ME

Today
Yesterday
Total
  • filter() - fields loopkups(**kwargs), Q objects(**args)
    Backend/Django 2023. 12. 3. 17:12

     

    Clone Coding을 하다가 생각없이 사용 중이던 filter() 함수의 사용법을 좀 더 깊게 파보고자 공식 문서를 살펴 보았다.


     

    filter()

    https://docs.djangoproject.com/en/4.2/ref/models/querysets/#filter

    QuerySet의 Member method 로 lookup parameter를 충족하는 객체들만 모아 새로운 QuerySet 을 생성하여 반환한다.

    즉 DB에서 특정 조건(lookup parameter)들로 조회하여 나온 결과를 다시 Model Instance로 생성하여 QuerySet에 담아 반환한다고 볼 수 있다.

     

    조건을 지정하는 방식으로는 field lookups(kwargs에 대입) 와Q object(args에 대입) 가 있다.

    여러 조건을 복잡하게 조합할 때(ex. OR, NOR)에는 Q object를 사용하는 것이 더 적합하다.

    Field lookups와 Q object롤 동시에 사용할 때에는 반드시 Q object가 Field lookups 보다 앞에 위치해야 한다. ( Python 문법을 따른다고 보면 된다. 함수 Parameter로 *args는 항상 **kwars보다 선언되어야 하므로)

     

     

    그럼 field lookups 란?

    더보기

    https://docs.djangoproject.com/en/4.2/ref/models/querysets/#field-lookups

     

    SQL의 WHERE 절에 사용될 조건들을 어 떤 방식으로 구체화할 것이지 결정하는 규칙이다. QuereSet의 filter(), get(), exclude() 등의 함수에서 lookup parameter(**kwargs) 에 사용된다.

     

    QuerySet을 검색할 때 사용할 Field 명 뒤에 double-underscore(__)로 연결한 field lookups를 사용한다.

    ex) QuerySetObj.objects.filter(id__exact=1)

    lookup parameter에 별도의 field lookups가 지정되지 않을 경우 100% 일치를 의미하는 exact 가 default로 사용된다.

     

    한 번에 여러 개의 field_lookups를 사용하는 것도 가능하다. 이 경우 모든 조건은 SQL문으로 치환 시  AND 연산으로 묶이는 효과를 보게된다.

    QuerySetObj.objects.filter(id__exact=1, name__startswith="Kim")

    => SELECT * FROM Table WHERE id==1 AND name LIKE "Kim%" 정도로 치환될 수 있다.

     

    exact(100% 일치), iexact(대소문자 무시), startswith(주어진 keyword로 시작), endwith (주어진 keyword로 끝) 등등의 규칙이 존재한다.(더 많은 종류는 위 Link에서 확인 가능)

     

    Django에서 기본 제공하는 규칙 외에도 custom lookups를 만들어 사용이 가능하다. (사용 해본 적 X, 아래 Link 참고)

    https://docs.djangoproject.com/en/4.2/howto/custom-lookups/

     

     

    더 복잡한 조건을 사용하고 싶을 땐 Q objects

    더보기

    이름에서 알 수 있듯 Q object는 SQL의 조건을 나타내는 '객체'이다.

    객체의 형태로 존재하므로 재사용이 가능하다.

    Q object 생성 시 생성자는 kwargs를 받는데 이때 전달 받는 값들은 Field lookups 를 따른다.

     

    &, |, ^ 와 같은 연산자로 연결될 수 있다.

    Q(question__startswith="who) | Q(question_starswith="what")

    이 경우 내부적으로는 두 개의 조건을 갖는 하나의 Q object가 생성되어 전달된다.

     

    Lookup 함수에서 쉼표(',') 로 두 개 이상의 Q object가 연결될 때에는  AND 연산으로 연결된다.

    QuerySet.objects.filter(Q(question__startswith='who'), Q(pub_date=(date(2023.12.14)))

    -> SELECT * FROM table WHERE question LIKE 'who%' AND pub_date="2023-12-14" 정도로 치환 될 수 있다.

     


    DB 공부를 할 때 LIKE 연산은 DB에 부하를 많이 주기 때문에 사용을 남발하면 안 된다고 배웠다. 

    그렇다면 Field lookups를 사용할 때에도 LIKE로 치환 될 것으로 예상되는 규칙들도 DB에 똑같이 부하를 많이 주게 되는 것일까?

    아니면 Django에서 내부적으로 어떤 처리를 하여 실제 SQL문에서 LIKE 연산을 사용하는 것 보다는 DB 부하가 덜한 것일까?

    이 점은 따로 조사가 필요하겠다.

    댓글

Designed by Tistory.