首选明确一点,这两个都是发生在表连接中,为了避免不必要的数据查询而存在
创建模型类
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=300)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length=300)
price = models.IntegerField(default=0)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
class Meta:
default_related_name = 'books'
def __str__(self):
return self.name
class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
class Meta:
default_related_name = 'stores'
def __str__(self):
return self.name
使用前:查到book的queryset,然后又到数据库中通过publisher.id查询publish.name,两次进入数据库,效率低
queryset = Book.objects.all()
books = []
for book in queryset:
books.append({'id': book.id, 'name': book.name, 'publisher': book.publisher.name})
return books
使用后:在第一次查询时通过SQL语句中使用join将数据预读取,就不用在此查询数据库,效率高
queryset = Book.objects.select_related('publisher').all()
books = []
for book in queryset:
books.append({'id': book.id, 'name': book.name, 'publisher': book.publisher.name})
return books
只能查询多对一或者一对一,也就是对象的外键属性是一个对象
如果是一个集合,就需要用到prefetch_related
使用前:第一次查询得到queryset,然后又对其中每个对象的"外键
"属性进行all查询效率低
queryset = Store.objects.all()
stores = []
for store in queryset:
books = [book.name for book in store.books.all()]
stores.append({'id': store.id, 'name': store.name, 'books': books})
return stores
使用后:分别查询每一个表,然后在python语言层面上进行连接,效率比前者高
queryset = Store.objects.prefetch_related('books')
stores = []
for store in queryset:
books = [book.name for book in store.books.all()]
stores.append({'id': store.id, 'name': store.name, 'books': books})
return stores
queryset = Store.objects.prefetch_related('books')
stores = []
for store in queryset:
books = [book.name for book in store.books.filter(price__range=(250, 300))]
stores.append({'id': store.id, 'name': store.name, 'books': books})
return stores
queryset = Store.objects.prefetch_related(
Prefetch('books', queryset=Book.objects.filter(price__range=(250, 300))))
stores = []
for store in queryset:
books = [book.name for book in store.books.all()]
stores.append({'id': store.id, 'name': store.name, 'books': books})
return stores
queryset = Store.objects.prefetch_related( Prefetch('books', queryset=Book.objects.filter(price__range=(250, 300))))