∟ 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

 

 

 

 

 

 

'∟ Framework > ∟ DRF' 카테고리의 다른 글

Redis를 Django 캐시 백엔드로 설정하기  (1) 2025.03.31
ORM 최적화  (0) 2025.03.31
Token Auth with JWT  (0) 2025.03.30
DRF Serializer 활용  (1) 2025.03.30
DRF models with relationship CRUD API 구현  (0) 2025.03.30