F 객체와 Q 객체를 활용한 고급 동적 쿼리 작성법
Django ORM에서 F()와 Q() 객체를 활용하여 데이터베이스 레벨에서 효율적인 필드 연산과 복잡한 동적 쿼리 조건을 구성하는 방법
F() 객체: 데이터베이스 레벨 필드 참조
F() 객체의 핵심 개념
모델의 필드 값 자체를 나타내는 객체
파이썬 메모리가 아닌 데이터베이스에서 직접 필드 값 참조 및 연산
SQL 쿼리로 변환될 때 해당 필드의 열 이름을 나타냄
필드 값 비교
# 재고가 최소 재고 수준보다 적은 상품 조회
low_stock_products = Product.objects.filter(stock_quantity__lt=F('minimum_stock_level'))Race Condition 방지를 위한 원자적 업데이트
# 조회수 증가 (안전한 방식)
Product.objects.filter(pk=1).update(hit_count=F('hit_count') + 1)annotate()와 함께 계산 필드 생성
# 할인율 적용한 최종 가격 계산
products_with_final_price = Product.objects.annotate(
final_price=F('price') * (1.0 - F('discount_rate'))
)Q() 객체: 복잡한 쿼리 조건 구성
Q() 객체의 핵심 개념
SQL의 WHERE 절을 캡슐화하는 객체
OR, AND, NOT 논리 연산자 조합으로 복잡한 쿼리 조건 생성
filter()의 콤마 구분은 AND 조건만 가능, OR 조건은 Q() 객체 필수
논리 연산자
&(AND): 두 조건을 모두 만족|(OR): 두 조건 중 하나라도 만족~(NOT): 조건을 만족하지 않음
OR 조건 쿼리 예시
# 제목에 'Django' 포함하거나 내용에 'Python' 포함한 게시물
Post.objects.filter(
Q(title__icontains='Django') | Q(content__icontains='Python')
)동적 쿼리 빌딩
def product_search(request):
query = Q(is_active=True)
keyword = request.GET.get('q')
if keyword:
query &= (Q(name__icontains=keyword) | Q(description__icontains=keyword))
category_id = request.GET.get('category')
if category_id:
query &= Q(category_id=category_id)
min_price = request.GET.get('min_price')
if min_price:
query &= Q(price__gte=min_price)
products = Product.objects.filter(query)F()와 Q() 객체 조합 활용
복합 조건 쿼리
# 재고량이 주문량보다 많고 특정 카테고리인 상품
products = Product.objects.filter(
Q(category=target_category) & Q(stock_quantity__gt=F('order_count'))
)커스텀 Manager/QuerySet 활용
class ProductQuerySet(models.QuerySet):
def low_on_stock(self):
return self.filter(stock_quantity__lt=F('minimum_stock_level'))
def search(self, keyword):
if not keyword:
return self
return self.filter(Q(name__icontains=keyword) | Q(description__icontains=keyword))
class Product(models.Model):
objects = ProductQuerySet.as_manager()Last updated
