∟ Framework/∟ DRF

Django ORM(Object Relational Mapping) 활용

최 수빈 2025. 3. 31. 01:24

 

Django에서 ORM(Object Relational Mapping)

 

데이터베이스 테이블을 파이썬 객체처럼 다룰 수 있게 해주는 기술

→ Python 쉘이나 view, script 안에서 실행할 수 있음

 

 

 

사전 준비하기

 

products 앱 생성, Product 모델 정의

python manage.py startapp products
# settings.py
INSTALLED_APPS = [
    ...,
    # Local
    "products",
    ...
]
# products/urls.py
from django.urls import path

urlpatterns = []
# urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/v1/articles/", include("articles.urls")),
    path("api/v1/accounts/", include("accounts.urls")),
    path("api/v1/products/", include("products.urls")),
]
# products/models.py

from django.db import models

class Product(models.Model):
    CATEGORY_CHOICES = (
        ("F", "Fruit"),
        ("V", "Vegetable"),
        ("M", "Meat"),
        ("O", "Other"),
    )

    name = models.CharField(max_length=100)
    price = models.PositiveIntegerField()
    quantity = models.PositiveIntegerField()
    category = models.CharField(max_length=1, choices=CATEGORY_CHOICES)

    def __str__(self):
        return self.name

 

price와 quantity는 양의 정수만 입력되도록 PositiveIntegerField 사용

category는 4가지 중 하나만 선택할 수 있도록 choices 설정 활용

 

 

마이그레이션

python manage.py makemigrations
python manage.py migrate

 

 

seed로 테스트 데이터 30개 생성

python manage.py seed products --number=30

django-seed를 사용하여 랜덤한 상품 데이터 생성

 

 

shell_plus 사용 준비

pip install django-extensions
# settings.py
INSTALLED_APPS = [
    ...,
    # Third-party
    "django_extensions",
    ...
]
python manage.py shell_plus

 

 

 

Django ORM을 이용하여 복합 조건, 집계 연산 처리 쿼리 사용하기

 

 

Q 객체: 복합 조건 처리

SQL의 WHERE 절에 해당하는 기능 활용 가능

 

OR 조건

가격이 15000 초과이거나 수량이 3000 미만인 상품 조회

Product.objects.filter(
    Q(price__gt=15000) | Q(quantity__lt=3000)
)

 

AND 조건

가격이 10000 초과이고 수량이 2000 미만인 상품 조회

Product.objects.filter(
    Q(price__gt=10000) & Q(quantity__lt=2000)
)

 

 

F 객체: 필드 값 참조

python 메모리로 값을 가져오지 않고 필요한 작업을 데이터베이스에서 수행 가능

 

기존 값 기반 업데이트

모든 상품의 가격을 1000원씩 인상

Product.objects.update(price=F('price') + 1000)

코드 실행 전
코드 실행 후

 

 

annotate(): 각 row에 계산 필드 추가

annotate == 주석을 달다

조회하는 쿼리셋 각각에 추가적인 정보(데이터)를 제공하는데 사용

 

 

총 가격 필드 추가

price × quantity를 계산하여 total_price 조회

products = Product.objects.annotate(
    total_price=F('price') * F('quantity')
)

for product in products:
    print(product.name, product.total_price)

 

 

aggregate(): 전체 데이터에 대한 집계

aggregate == 종합/집약하다

주로 집계 함수(Avg, Sum, Count 등)와 사용

 

평균 가격 구하기

Product.objects.aggregate(my_avg=Avg('price'))

 

 

카테고리별 상품 수 세기

 

잘못된 방식 (전체 개수만 나옴)

Product.objects.aggregate(Count('category'))
# {'category__count': 30}

 

올바른 방식: Group By 적용

Product.objects.values('category').annotate(
    category_count=Count('category')
)
# [{'category': 'F', 'category_count': 6}, {'category': 'M', 'category_count': 11}, {'category': 'O', 'category_count': 11}, {'category': 'V', 'category_count': 2}]

 

 

 

Raw SQL 직접 사용하기

 

Raw() 활용

categories_count = Product.objects.raw(
    '''
    SELECT "id", "category", COUNT("category") AS "category_count" 
    FROM "products_product" 
    GROUP BY "category"
    '''
)

for each in categories_count:
    print(each.category, each.category_count)
    
"""
F 6
M 11
O 11
V 2
"""

 

DB 커넥션 사용

from django.db import connection

sql_query = '''
SELECT "category", COUNT("category") AS "category_count" 
FROM "products_product" 
GROUP BY "category"
'''

cursor = connection.cursor()
cursor.execute(sql_query)
result = cursor.fetchall()
print(result)
# [('F', 6), ('M', 11), ('O', 11), ('V', 2)]

 

 

 

Q 객체

 

Making queries | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

F 객체

 

Query Expressions | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

annotate

 

QuerySet API reference | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

aggregate

 

QuerySet API reference | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com