Django

Q 객체

traveler_JH 2022. 7. 6. 22:48

장고를 통한 팀프로젝트중 다중 조건 필터를 걸어야했고 이에 Q객체를 사용하여 문제를 해결하였다.

장고 ORM에서 쿼리문처럼 or 조건을 쓰고 싶을때 사용

#sql 쿼리문
select * from product where category=소 or sub_category=등심

#장고 ORM
Product.objects.filter(Q(category=소)|(category=등심))

&을 사용하면 where 조건의 and 즉 조건 전체를 만족하는 결과값만 보여준다. == 교집합

| 를 사용하면 where 조건의 or조건 이다 둘중 하나라도 조건에 맞으면 그 결과 값을 전부다 보여준다. == 합집합

Q()

from django.db.models       import Q
from django.http            import JsonResponse
from django.views           import View

from products.models import Image, ProductColor

class ProductListView(View): 
    def get(self, request): 
        category = request.GET.getlist('category', None)
        color= request.GET.getlist('color',None)
        product = request.GET.get('product',None)
        price_upper_range  = request.GET.get('priceupper',100000000)
        price_lower_range  = request.GET.get('pricelower',0)
        result=[]
        
        q = Q()

        if category:
            q &= Q(product__category_id__in = category)

        if product:
            q &= Q(product__name__istartswith = product)
                       
        if color :
            q &= Q(color__name__in = (color))

        q &= Q (product__price__range = (price_lower_range, price_upper_range))

        products = ProductColor.objects.filter(q) 

        result=[{
            "primary_key" : pc.id,
            "category" : pc.product.category.name,
            "name" :  pc.product.name,
            "color" : pc.color.name,
            "price" : pc.product.price,
            "image" : [image.image_url for image in Image.objects.filter(product_color_id = pc.id, sequence=1)]       
        }for pc in products]
        
        return JsonResponse({"result":result}, status=200)

&= , |= 사용하는 경우

   q = Q()

        if category:
            q &= Q(product__category_id__in = category)

        if product:
            q &= Q(product__name__istartswith = product)
                       
        if color :
            q &= Q(color__name__in = (color))

        q &= Q (product__price__range = (price_lower_range, price_upper_range))

        products = ProductColor.objects.filter(q) 

Q() 은 Product.objects.all() 과 똑같다.

Product 전체를 변수에 담아두고, q변수 안에 조건들을 넣어주는 느낌!

즉,

q &= Q(sub_category__category__name=category)

는 q라는 변수안에 조건들을 하나하나 넣어주고 마지막 filter에 그 변수를 넣어서 쿼리를 한번만 날려도 되도록 해준다.

'Django' 카테고리의 다른 글

DB 덤프파일 만들기  (0) 2022.07.06
자주 사용되는 HTTP Status Code 와 Text  (0) 2022.07.06
Decorator  (0) 2022.07.06
쿼리 스트링 불러오기  (0) 2022.07.06
CSV Uploader  (0) 2022.07.06