오늘은 Django의 ORM과 QuerySet에 대해 알아보고자 한다.
Django ORM과 QuerySet
- ORM (Object Relational Mapping)
ORM이란 Object Relational Mapping의 약자로 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해 주는 기술을 의미한다. 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 SQL 쿼리문 없이도 데이터베이스 데이터를 다룰 수 있게 해 준다.
- QuerySet
QuerySet이란 데이터베이스에서 전달받은 객체들의 모임을 말한다. Django에서는 ORM을 사용하여 각 객체를 관계형 데이터베이스와 매핑해서 사용하는데 이때 모델과 데이터베이스 간의 연산을 수행하기 위해 모델매니저(Model Manager)가 존재한다. 이때 사용하는 매개체가 "objects"이며, 해당 연산의 결과로 나온 객체목록을 쿼리 셋이라고 한다.
쿼리 표현식
- all() : 해당 모델 테이블의 모든 데이터를 조회한다.
Post.obejcts.all()
# <QuerySet [<Post: Post object (1)>, <Post: Post object (2)>, <Post: Post object (3)> ..]
- filter(): 특정 조건에 맞는 데이터를 조회한다.
Post.obejcts.filter(id=1)
# <QuerySet [<Post: Post object (1)>]>
- exclude(): 특정 조건을 제외한 나머지 데이터를 조회한다.
Post.obejcts.exclude(id=1)
# <QuerySet [<Post: Post object (2)>, <Post: Post object (3)>, <Post: Post object (4)> ...]>
- values(): 쿼리 셋 내용을 딕셔너리형태로 반환한다. 인자값에 특정 필드를 입력하면 입력한 필드에 대한 값을 반환한다.
Post.obejcts.values()
# <QuerySet [{"id":1, "title":"PostTitle_1"}, {"id":2, "title":"PostTitle_2"} ...]>
- values_list(): 쿼리 셋 내용을 리스트 타입으로 반환한다. 인자값에 특정 필드를 입력하면 입력한 필드에 대한 값을 반환한다.
Post.obejcts.values_list()
# <QuerySet [(1,"PostTitle_1"), (2, "PostTitle_2") ...]>
- order_by(): 특정 필드 기준으로 정렬한다. 기본적으로 오름차순이며 필드 앞에 -을 붙이면 내림차순으로 정렬한다.
Post.obejcts.order_by("-id")
# <QuerySet [<Post: Post object (100)>, <Post: Post object (99)>, <Post: Post object (98)> ...]>
- get(): 조건에 맞는 하나의 데이터 조회하며 객체 타입으로 반환한다.
Post.obejcts.get(id=1)
# <Post: Post object (1)>
- create(): 하나의 데이터를 생성하고, 해당 모델 데이터를 반환한다.
Post.obejcts.create()
# <Post: Post object (1)>
- bulk_create(): 여러 개의 오브젝트를 한 번에 만들 때 사용한다.
Post.objects.bulk.create([
Post(),
Post(),
Post(),
)
# [<Post: Post obejct <1>>, <Post: Post obejct <2>>, <Post: Post obejct <3>>]
- get_or_craete(): 객체가 주어진 조건에 이미 있다면 get 해오고 아니면 create 한다.
post = Post.objects.get_or_create(id=1)
- latest(): 주어진 필드 기준으로 가장 최신의 모델 데이터를 반환
Post.objects.all().latest()
# <Post: Post object <100>>
- first(), last(): 쿼리 셋 결과 중 가장 첫 번째, 마지막 행을 조회할 때 사용한다.
Post.objects.all().first()
# <Post: Post object <1>>
Post.objects.all().last()
# <Post: Post object <100>>
- count(): 쿼리 셋에 포함된 데이터의 개수를 조회할 때 사용한다.
Post.objects.all().count()
# 100
- exists(): 해당 테이블에 데이터가 있는지 확인할 때 사용하며 True, False을 반환한다.
Post.objects.filter(id=1).exists()
# True
Post.objects.filter(id=101).exists()
# False
- update(): 데이터를 수정할 때 사용한다.
post = Post.objects.get(id=1)
post.update(title="Title", contents="Contents")
- delete(): 데이터를 삭제할 때 사용한다.
post = Post.objects.get(id=1)
post.delete()
Django ORM의 특징
- 지연로딩 (Lazy-loading)
지연로딩이란 ORM에서 명령를 실행할 때마다 데이터베이스에 접근하여 데이터를 가져오는 것이 아니라, 모든 명령처리가 끝나고 실제 데이터를 불러와야 할 때 데이터베이스 쿼리문을 실행하는 방식을 말한다. 성능차원에서 데이터베이스의 접속을 최소화하기 위해서 사용하지만 비효율적인 쿼리가 발생하기도 한다.
posts = Post.objects.all() # DB에서 호출 X
list(posts) # DB에서 호출 O
- 캐싱 (caching)
각 쿼리 셋은 데이터베이스의 접속을 최소화하기 위해 캐시(cache)를 가지고 있다. 쿼리문이 실행되기 전엔 캐시가 비어있지만 실행 후에 쿼리 수행 결과를 캐시에 저장해 둔다. 참고로 쿼리 셋이 항상 캐시 되는 것이 아니다. slice, index를 통해 쿼리 셋을 제한하면 캐시에 저장되지 않으니 유의할 것
results = Product.objects.all()
results_list = list(results) # 쿼리 수행 및 수행결과 캐시에 저장
results_list[1] # 캐시 되어 있는 데이터를 이용하여 쿼리 수행 X
results_list[2]
results_list[3]
results = Product.objects.all()
results[1] # 쿼리 수행 및 수행결과 캐시에 저장
results[2] # 캐시에 되어 있는 데이터가 없어 쿼리 수행 O
results[3] # 캐시에 되어 있는 데이터가 없어 쿼리 수행 O
results[4] # 캐시에 되어 있는 데이터가 없어 쿼리 수행 O
'FrameWork > Django' 카테고리의 다른 글
N + 1 쿼리 문제 (0) | 2024.07.10 |
---|---|
select_related와 prefetch_related (0) | 2024.07.10 |
django-seed을 통해 더미데이터 만들기 (0) | 2023.12.13 |
settings.py 분리하여 관리하기 (1) | 2023.11.23 |
dumpdata와 loaddata을 통해 DB데이터 추출, 적재하기 (1) | 2023.11.23 |