본문 바로가기
Django

[Django] F객체, Q객체란? - ORM에서 F,Q 사용하기(짤막팁 2편)

by kyung-mini 2024. 9. 8.

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_soldstock 보다 큰 경우를 찾습니다.

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을 사용한다면 자주 사용하게 되실 것이라 생각합니다. 따라서, 친숙해지면 좋을 것 같습니다.