Django
django | prefetch_related()
JOOHUUN
2022. 8. 13. 19:21
prefetch_related
구하려는 객체가 정참조 multiple objects(many-to-many or one-to-many)이거나, 또는 역참조 Foreign Key일때 사용한다.
# Create your models here.
from django.db import models
class Topping(models.Model):
name = models.CharField(max_length=30)
class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)
def __str__(self):
return "%s (%s)" % (
self.name,
", ".join(topping.name for topping in self.toppings.all()),
)
1. 장고셸을 사용해서 데이터 넣기
from prefetch_related.models import Topping, Pizza
q=Topping(name="양파")
q.save()
q=Topping(name="고구마")
q.save()
q=Topping(name="감자")
q.save()
Topping.objects.all()
<QuerySet [<Topping: 양파>, <Topping: 고구마>, <Topping: 감자>]>
2. prefetch_related
>>> Pizza.objects.all()
<QuerySet [<Pizza: 고구마 피자 (양파, 고구마)>, <Pizza: 포테이토 피자 (양파, 감자)>]>
Pizza.objects.all()은 요청할 때마다 self.toppings.all() 데이터베이스를 쿼리해야 하므로
모든 피자 항목에 대해 Toppings 테이블에서 쿼리를 실행한다.
>>> Pizza.objects.prefetch_related('toppings')
<QuerySet [<Pizza: 고구마 피자 (양파, 고구마)>, <Pizza: 포테이토 피자 (양파, 감자)>]>
prefetch_related('toppings)는 self.toppings.all()을 의미하며 self.toppings.all() 항목에 대한 데이터 베이스로 이동하여 쿼리를 실행하지 않고 미리 단일 쿼리로 채워진 캐시를 읽어 쿼리를 실행한다.
In [44]: Topping.objects.all()
Out[44]: <QuerySet [<Topping: 양파>, <Topping: 고구마>, <Topping: 감자>, <Topping: 치즈>, <Topping: 불고기>]>
Toppings의 모든 객체를 읽어 오지 않고 관련 객체만 읽어 오므로 쿼리 속도가 빨라진다.
예를 들면 고구마 피자의 토핑에는 양파, 고구마 두가지가 있는데 이 데이터를 가져올때 모든 토핑을 거치지 않고 미리 캐시에 저장된 두 가지 토핑만 읽으면 된다.