更少的查询
本课属于 Coddy Django 学习旅程的“模型和管理后台”单元。第 19 课,共 23 课。
主页会打印每本书的作者,这需要付出代价:一个查询获取所有书籍,然后每本书的 {{ book.author.name }} 都会再运行一个查询。10 本书需要 11 个查询,1000 本书需要 1001 个查询。这就是 N+1 问题,也是 Django 页面运行缓慢的常见原因。
select_related() 可以解决这个问题:ORM 会通过 SQL JOIN 在同一个查询中获取关联的行。一个会打印每笔借阅的书名的页面需要这样写:
loans = Loan.objects.select_related("book")把 ForeignKey 字段的名称传给它,也就是你通过 loan.book 读取的那个字段,而且它仍然可以和 filter()、order_by() 连用。它只会沿着 ForeignKey 正向关联。要获取作者的书籍或处理多对多字段,你需要使用 prefetch_related(),Authors 项目中用到了它。之后页面看起来一样,但查询次数更少。
挑战
中等在 books/views.py 中,让 home 和 search 中的 QuerySet 在同一次查询中获取每本书的作者。保留搜索筛选条件。
按“运行”:页面看起来没有变化。检查会添加 10 本书,并允许每个页面执行两次查询。
亲手试试
from django.shortcuts import get_object_or_404, render
from .models import Book
def home(request):
books = Book.objects.all()
return render(request, "books/home.html", {"books": books})
def book_detail(request, pk):
book = get_object_or_404(Book, pk=pk)
return render(request, "books/book_detail.html", {"book": book})
def search(request):
q = request.GET.get("q", "")
books = Book.objects.filter(title__icontains=q)
return render(request, "books/search.html", {"q": q, "books": books})
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
模型和管理后台中的所有课
自己练习: Django 在线编辑器