One to one relationships

One to one 필드가 있는 모델에 데이터를 저장하려고 한다. 해당 필드를 조건으로 조회하게 될 경우 ObjectDoesNotExist 에러가 발생한다. One to one 필드에 관련된 데이터가 없기 때문이다.

One-to-one relationships문서에 두 가지가 해결방법이 있다.

  1. try, except 처리
  2. hasattr 사용

QuerySet

select_related()

  • ForeignKey, OneToOneField 관계에서 활용
  • ForeignKey/OneToOneField 관계에서 Lazy하게 쿼리하지 않고, DB단에서 INNER JOIN 으로 쿼리할 수 있다.

prefetch_related()

  • ManyToManyField, ForeignKey의 reverse relation 에서 활용
  • 각 관계 별로 DB 쿼리를 수행하고, 파이썬 단에서 조인을 수행한다.

django 쿼리셋 수정을 통한 웹서비스 성능 개선 - select_related, prefetch_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())