1. 개요
이번 포스팅은 Django의 ORM에서 사용되는 F객체와 Q객체에 대해 알아보겠습니다.
2. F객체
2.1 F객체란?
DB 레벨에서 데이터를 직접 연산하거나 참조할 수 있도록 도와주는 객체입니다. 이를 사용하면 데이터를 메모리로 쿼리셋 형태로 불러오지 않습니다. 연산은 DB에서 직접 수행하기 때문에 효율적입니다. 주로 다음과 같은 세 가지 목적을 위해 사용합니다.
- 필드 간의 값 비교
- 필드 값을 이용한 계산
- 필드 값의 업데이트
2.2 F객체 사용법
예시로 사용할 Product
모델의 코드와 테이블 구조입니다.
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255) # 상품 이름
stock = models.IntegerField() # 재고 수량
quantity_sold = models.IntegerField() # 판매량
selling_price = models.IntegerField() # 판매 가격
def __str__(self):
return self.name
id | name | stock | quantity_sold | selling_price |
1 | Laptop | 50 | 60 | 1000 |
2 | Smartphone | 100 | 80 | 500 |
3 | Headphones | 200 | 50 | 100 |
2.2.1 필드 간의 값 비교
재고보다 판매량이 많은 상품을 찾는 예제를 보겠습니다.
from django.db.models import F
over_sold_products = Product.objects.filter(quantity_sold__gt=F('stock'))
위 코드에서는 quntity_sold
가 stock
보다 큰 경우를 찾습니다.
Laptop
의 경우 판매량(60) > 재고(50) 이기 때문에 over_sold_product
에 포함됩니다.
id | name | stock | quantity_sold | selling_price |
1 | Laptop | 50 | 60 | 1000 |
(참고 : print(over_sold_products)
를 통해 출력된 값은<QuerySet [<Product: Laptop>]
>
입니다.)
2.2.2 필드 값을 이용한 계산
각 상품의 총 판매액을 계산하는 예시입니다. (총 판매액 = 판매 수량 X 상품 가격)
from django.db.models import F
products = Product.objects.annotate(total_sales=F('quantity_sold') * F('selling_price'))
# annotate : 총 판매액 필드 추가
위 코드는 total_sales
라는 필드를 추가한 쿼리셋을 반환합니다.
id | name | stock | quantity_sold | selling_price |
1 | Laptop | 50 | 60 | 1000 |
2 | Smartphone | 100 | 80 | 500 |
3 | Headphones | 200 | 50 | 100 |
(참고 : print(over_sold_products)
를 통해 출력되는 값은 <QuerySet [<Product: Laptop> , <Product: Smartphone> , <Product: Headphones> ]
>
입니다.)
2.2.3 값의 업데이트
F객체를 사용하면 필드 값을 동적으로 업데이트 할 수 있습니다. 판매량만큼 재고를 감소시켜야 한다고 가정하겠습니다.
from django.db.models import F
Product.objects.update(stock=F('stock') - F('quantity_sold'))
아래와 같은 쿼리셋이 반환됩니다.
id | name | stock | quantity_sold | selling_price |
1 | Laptop | -10 | 60 | 1000 |
2 | Smartphone | 20 | 80 | 500 |
3 | Headphones | 150 | 50 | 100 |
(참고 : print(over_sold_products)
를 통해 출력되는 값은 <QuerySet [<Product: Laptop> , <Product: Smartphone> , <Product: Headphones> ]
>
입니다.)
3. Q객체
3.1 Q객체란?
Django의 ORM에서 논리 연산을 사용한 필터링을 도와주는 도구입니다. filter()
메서드는 AND
조건으로 처리됩니다. 하지만, Q객체를 사용하면 다음과 같은 세 가지 논리 연산을 결합할 수 있습니다.
- OR
- AND
- NOT
3.2 Q객체 사용 법
예시로 사용될 Product
모델의 코드와 테이블 구조입니다.
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255) # 상품 이름
stock = models.IntegerField() # 재고 수량
quantity_sold = models.IntegerField() # 판매량
selling_price = models.IntegerField() # 판매 가격
def __str__(self):
return self.name
id | name | stock | quantity_sold | selling_price |
1 | Laptop | 50 | 60 | 1000 |
2 | Smartphone | 100 | 80 | 500 |
3 | Headphones | 200 | 150 | 100 |
4 | Tablet | 30 | 10 | 200 |
3.2.1 OR 연산
판매 가격이 1000 이상이거나, 재고가 50 이하인 상품을 찾는 예시입니다.
from django.db.models import Q
products = Product.objects.filter(Q(selling_price__gte=1000) | Q(stock__lte=50))
위 코드는 selling_price
가 1000 이상이거나 stock
이 50 이하인 쿼리셋을 반환합니다.
id | name | stock | quantity_sold | selling_price |
1 | Laptop | 50 | 60 | 1000 |
4 | Tablet | 30 | 10 | 200 |
(참고: print(product)
를 실행하면 QuerySet [<Product: Laptop>, <Product: Tablet>]
이 출력됩니다.)
3.2.2 AND 연산
filter()
메서드는 AND
연산이지만, Q객체를 사용해 명시적으로 나타낼 수 있습니다.
판매 가격이 500 이상이면서 재고가 100 이상인 상품을 찾는 예시입니다.
from django.db.models import Q
products = Product.objects.filter(Q(selling_price__gte=500) & Q(stock__gte=100))
위 코드는 selling_price
가 500 이상이면서, stock
가 100 이상인 쿼리셋를 반환합니다.
id | name | stock | quantity_sold | selling_price |
2 | Smartphone | 100 | 80 | 500 |
3 | Headphones | 200 | 150 | 100 |
(참고: print(product)
를 실행하면 QuerySet [<Product: Smartphone>, <Product: Headphones>]
이 출력됩니다.)
3.2.3 NOT 연산
~
연산자를 사용하여 조건을 부정할 수 있습니다.
재고가 100이하가 아닌 상품을 찾는 예시입니다.
from django.db.models import Q
products = Product.objects.filter(~Q(stock__lte=100))
이 코드는 stock
이 100이하가 아닌 쿼리셋을 반환합니다.
id | name | stock | quantity_sold | selling_price |
3 | Headphones | 200 | 150 | 100 |
(참고: print(products)를 실행하면 QuerySet [<Product: Headphones>]이 출력됩니다.)
4. 마무리
이번 포스팅에서는 F객체와 Q객체에 대해서 알아보았습니다.
F객체에서는 필드 값 간의 비교, 계산, 업데이트를 효율적으로 처리할 수 있습니다.
Q객체에서는 OR
, AND
, NOT
연산을 사용하여 복잡한 필터링 조건을 구현할 수 있습니다.
Django에서 ORM을 사용한다면 자주 사용하게 되실 것이라 생각합니다. 따라서, 친숙해지면 좋을 것 같습니다.
'Django' 카테고리의 다른 글
[Django] select_related(), prefetch_related()란?(N+1문제 해결법) (1) | 2024.09.19 |
---|---|
[Django] annotate()란? - annotate 사용법(with. only(),values() 쿼리 최적화) (0) | 2024.09.13 |
[Django] Signals 사용법 - 프로필 자동 생성, 좋아요 숫자 갱신(signal 표로 정리) (2) | 2024.09.05 |