참고자료
udemy 강의(shopping cart)
Q 객체를 사용한 복잡한 조회
부제: 검색 조건이 복잡하면 Q models 를 불러와서 정의하자.
Post.objects.filter() 는 AND 연산자가 포함이 된다. 그렇기 때문에 OR 문을 실행해야 하는 경우에는 Q objects 를 사용
[comment] 즉, A 와 B 를 포함하는 모든 검색 조건에 대해서 검색하라. 라는 것이 Q 객체를 사용하는 이유
from django.db.models import Q
Q(question__startswith='What')
Q objects 는 & 와 |(파이프라인: or 연산자) 의 사용이 가능하다. 연산자가 두 개의 Q 객체에 사용되면 새로운 Q 객체가 생성
예를 들어, 아래의 예제는 2개의 question__startswith 쿼리의 OR 을 나타내는 단일 Q 객체를 생성한다.
Q(question__startswith='Who' | Q(question__startswith='What')
이것은 아래의 SQL WHERE 절과 동일하다.
WHERE question LIKE 'Who%' OR question LIKE 'What%'
Q objects 를 & 와 |(파이프라인) 으로 결합하여 임의의 복잡성을 갖는 문장을 작성.
연산자 및 괄호 그룹화를 사용하는데, Q objects 는 '~' 연산자를 사용하여 무효화할 수 있으므로 일반 쿼리와 부정(NOT) 쿼리를 결합한 조회를 허용
Q(question__startswith='Who' | ~Q(pub_date__year=2005)
키워드 인수(filter(), exclude(), get()) 을 사용하는 각 조회 함수는 하나 이상의 Q objects 를 위치 지정되지 않은 인수로 전달할 수 있다.
조회 함수에 여러 개의 Q objects 인수를 제공하면 인수가 AND 가 된다.
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
SQL 문으로 작성
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
조회 함수(Lookup functions) 는 Q objects 와 키워드 인수의 사용을 혼합할 수 있다.
조회 함수에 제공된 모든 인수(키워드 인수 또는 Q objects) 는 함께 AND 된다.
그러나 Q objects 가 제공되면 키워드 인수의 정의 앞에 와야 한다.
[comment] (1순위) 모든 조건에 해당하는 검색조건 (2순위) 연산자가 들어간 상세 조건
# 올바른 예시
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2) | pub_date=date(2005, 5, 6)),
)
# 잘못된 예시
# INVALID QUERY
Poll.objects.get(
Q(pub_date=date(2005, 5, 2) | pub_date=date(2005, 5, 6)),
question_startswith='Who',
)
강의를 통해 실제 적용한 예시
- 쉬운 이해를 위해 실제 적용한 예시를 변형
shop/base.html
- 메인 페이지에서 name='q' 에 대한 객체를 받아 search.html 에서 검색결과를 보여줌
<#form method="GET" action="{% url 'search_app:search_result %}">
{% csrf_token %}
<# input type="search" name="q">
<# button type="submit">찾기
<#/form>
search_app/search.html
- base.html 에서 입력 -> search 템플릿에서 검색 결과를 보여줌
{% for product in products %}
{{ product.name }}
{{ product.price }}
{% empty %}
검색결과: 0개의 상품
{% endfor %}
search_app/urls.py
from . import views
urlpatterns = [
path('', views.search_result, name='search_result)
]
search_app/views.py
- if 'q' in reuqest.GET : form 에서 GET 요청으로 q(검색어) 를 입력했다면,
- query 에 해당 objects 를 담고 -> Product 의 모델에서 일치하는 조건만 렌더 시킨다
from django.shortcuts import render
from django.db.models import Q
from shop.models import Product
def search_result(request):
query = None
products = None
if 'q' in request.GET:
query = request.GET.get('q')
products = Product.objects.all().filter(Q(name__contains="query") | Q(description__contains="query"))
return render(request, 'search_app/search.html', {'query': query, 'products': products}
'장고 > MTV' 카테고리의 다른 글
try, except 와 if else 를 써야할 때 (0) | 2019.03.14 |
---|---|
AbstractBaseUser 모델 (0) | 2019.03.01 |
구문 분석 오류(could not parse ...) (1) | 2019.02.20 |
redirect 기능 (0) | 2019.02.19 |
장고 폼(bound form, unbound form, cleaned_data, is_valid) (0) | 2019.01.21 |