One to one relationships
One to one 필드가 있는 모델에 데이터를 저장하려고 한다. 해당 필드를 조건으로 조회하게 될 경우 ObjectDoesNotExist
에러가 발생한다. One to one 필드에 관련된 데이터가 없기 때문이다.
One-to-one relationships문서에 두 가지가 해결방법이 있다.
try
,except
처리hasattr
사용
QuerySet
select_related()
- ForeignKey, OneToOneField 관계에서 활용
- ForeignKey/OneToOneField 관계에서 Lazy하게 쿼리하지 않고, DB단에서 INNER JOIN 으로 쿼리할 수 있다.
prefetch_related()
- ManyToManyField, ForeignKey의 reverse relation 에서 활용
- 각 관계 별로 DB 쿼리를 수행하고, 파이썬 단에서 조인을 수행한다.
[django 쿼리셋 수정을 통한 웹서비스 성능 개선 - select_related, prefetch_related](https://wayhome25.github.io/django/2017/06/20/selected_related_prefetch_related/
select_related()
외래키 관계를 따르는 쿼리셋을 반환한다. 쿼리를 실행할 때, 추가적인 객체 데이터를 조회한다. 이것은 성능을 향상시킨다.
다음 예제는 일반 조회와 select_related()
조회 간의 차이점을 보여준다. 다음은 일반 조회이다.
# Hits the database.
e = Entry.objects.get(id=5)
# Hits the database again to get the related Blog object.
b = e.blog
select_related
조희는 다음과 같다.
# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)
# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog
select_related()
는 객체의 쿼리셋과 함께 사용할 수 있다.
from django.utils import timezone
# Find all the blogs with entries scheduled to be published in the future.
blogs = set()
for e in Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog'):
# Without select_related(), this would make a database query for each
# loop iteration in order to fetch the related blog for each entry.
blogs.add(e.blog)
filter()
및 select_related()
체이닝의 순서는 중요하지 않다. 아래 쿼리셋은 동등하다.
Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())