Django 减少对ForeignKey字段的查询数量(n + 1个问题)
示例
问题
Django查询集以惰性方式求值。例如:
# models.py: class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author, related_name='books') title = models.CharField(max_length=100)
# views.py def myview(request): # Query the database books = Book.objects.all() for book in books: # Query the database on each iteration to get author (len(books) times) # if there is 100 books, there will have 100 queries plus the initial query book.author # ... # total : 101 queries
上面的代码使django在数据库中查询每本书的作者。这样效率低下,最好只包含一个查询。
解
使用select_related上ForeignKey,如果你知道你将需要以后访问一个ForeignKey领域。
# views.py def myview(request): # Query the database. books = Books.objects.select_related('author').all() for book in books: # Does not query the database again, since `author` is pre-populated book.author # ... # total : 1 query
select_related也可以用于查找字段:
# models.py: class AuthorProfile(models.Model): city = models.CharField(max_length=100) class Author(models.Model): name = models.CharField(max_length=100) profile = models.OneToOneField(AuthorProfile) class Book(models.Model): author = models.ForeignKey(Author, related_name='books') title = models.CharField(max_length=100)
# views.py def myview(request): books = Book.objects.select_related('author')\ .select_related('author__profile').all() for book in books: # Does not query database book.author.name # or book.author.profile.city # ... # total : 1 query