-
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 참고)
더 복잡한 조건을 사용하고 싶을 땐 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 부하가 덜한 것일까?
이 점은 따로 조사가 필요하겠다.
'Backend > Django' 카테고리의 다른 글
[QuerySet] Django 의 DB 접근법 (2): Eager Loading (부제: DB 최적화 전략) (0) 2025.01.05 [QuerySet] Django 의 DB 접근법 (1): Lazy loading (3) 2024.11.10 VS Code에서 Django Debug 설정 (0) 2023.10.15 PyCharm에서 Django 디버그 모드 활성화하기 (0) 2023.10.10 class Meta (2) 2023.09.18