从多个模型中获取信息时优化 django 查询
Optimise django query when fetching information from multiple models
我是 Django 新手,使用的是 Django 3.0.6。
使用下面的代码,我已经能够达到预期的效果并将详细的书籍信息显示到模板上。但是,平均而言,ORM 会进行 8 到 9 次数据库查询以获取有关该书的详细信息。我正在寻找专家帮助来优化我的数据库查询,以便我可以用更少的查询来获取与图书相关的信息。
我尝试使用 select_related()
和 prefetch_related()
但没有任何运气,也许我做的不正确。是否有使用 Q object
或 union()
的范围,只是我的想法?我怎样才能用最少的数据库查询获得相同的结果?
如果可能,请帮我提供详细的代码。
models.py
class Publisher(models.Model):
publisher_name = models.CharField(max_length=50)
class Author(models.Model):
author_name = models.CharField(max_length=50)
class Booktype(models.Model):
book_type = models.CharField(max_length=20) # Hard Cover, Soft Cover, Kindle Edition, Digital PDF etc.
class Book(models.Model):
book_title = models.TextField()
slug = models.SlugField(max_length=50, unique=False)
published_date = models.DateField(auto_now=False, auto_now_add=False)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
book_type = models.ManyToManyField(Booktype, through='BookPrice', through_fields=('book', 'book_type'))
# I created this separate model due to havy content and to keep Book model light
class BookDetail(models.Model):
a = models.TextField(null=True, blank=True)
b = models.TextField(null=True, blank=True)
c = models.TextField(null=True, blank=True)
book = models.OneToOneField(Book, on_delete=models.CASCADE)
class BookPrice(models.Model):
book_type = models.ForeignKey(Booktype, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2)
view.py
def get_book_details(request, book_id, slug):
book = Book.objects.get(id=book_id, slug=slug)
context = {'book': book}
return render(request, 'products/book_detail.html', context)
book_detail.html 模板
# 1st databse query
{{ book.book_title }}
{{ book.id }}
{{ book.published_date }}
# 2nd databse query
{{ book.publisher.publisher_name }}
# 3rd databse query
{{ book.author.author_name }}
# 4th databse query
{{ book.bookdetail.a }}
{{ book.bookdetail.b }}
{{ book.bookdetail.c }}
# 5th to 9th databse query depending upon avaialble Book Types
{% for x in book.bookprice_set.all %}
{{ x.book_type }} {{ x.price|floatformat }}
{% endfor %}
您可以使用 .select_related(…)
[Django-doc] 来获取 publisher
、author
和 bookdetail
。我们可以使用 prefetch_related
def get_book_details(request, book_id, slug):
book = Book.objects.select_related(
<b>'publisher', 'author', 'bookdetail'</b>
).prefetch_related(
<b>'bookprice_set', 'bookprice_set__book_type'</b>
).get(id=book_id, slug=slug)
context = {'book': book}
return render(request, 'products/book_detail.html', context)
我是 Django 新手,使用的是 Django 3.0.6。
使用下面的代码,我已经能够达到预期的效果并将详细的书籍信息显示到模板上。但是,平均而言,ORM 会进行 8 到 9 次数据库查询以获取有关该书的详细信息。我正在寻找专家帮助来优化我的数据库查询,以便我可以用更少的查询来获取与图书相关的信息。
我尝试使用 select_related()
和 prefetch_related()
但没有任何运气,也许我做的不正确。是否有使用 Q object
或 union()
的范围,只是我的想法?我怎样才能用最少的数据库查询获得相同的结果?
如果可能,请帮我提供详细的代码。
models.py
class Publisher(models.Model):
publisher_name = models.CharField(max_length=50)
class Author(models.Model):
author_name = models.CharField(max_length=50)
class Booktype(models.Model):
book_type = models.CharField(max_length=20) # Hard Cover, Soft Cover, Kindle Edition, Digital PDF etc.
class Book(models.Model):
book_title = models.TextField()
slug = models.SlugField(max_length=50, unique=False)
published_date = models.DateField(auto_now=False, auto_now_add=False)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
book_type = models.ManyToManyField(Booktype, through='BookPrice', through_fields=('book', 'book_type'))
# I created this separate model due to havy content and to keep Book model light
class BookDetail(models.Model):
a = models.TextField(null=True, blank=True)
b = models.TextField(null=True, blank=True)
c = models.TextField(null=True, blank=True)
book = models.OneToOneField(Book, on_delete=models.CASCADE)
class BookPrice(models.Model):
book_type = models.ForeignKey(Booktype, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2)
view.py
def get_book_details(request, book_id, slug):
book = Book.objects.get(id=book_id, slug=slug)
context = {'book': book}
return render(request, 'products/book_detail.html', context)
book_detail.html 模板
# 1st databse query
{{ book.book_title }}
{{ book.id }}
{{ book.published_date }}
# 2nd databse query
{{ book.publisher.publisher_name }}
# 3rd databse query
{{ book.author.author_name }}
# 4th databse query
{{ book.bookdetail.a }}
{{ book.bookdetail.b }}
{{ book.bookdetail.c }}
# 5th to 9th databse query depending upon avaialble Book Types
{% for x in book.bookprice_set.all %}
{{ x.book_type }} {{ x.price|floatformat }}
{% endfor %}
您可以使用 .select_related(…)
[Django-doc] 来获取 publisher
、author
和 bookdetail
。我们可以使用 prefetch_related
def get_book_details(request, book_id, slug):
book = Book.objects.select_related(
<b>'publisher', 'author', 'bookdetail'</b>
).prefetch_related(
<b>'bookprice_set', 'bookprice_set__book_type'</b>
).get(id=book_id, slug=slug)
context = {'book': book}
return render(request, 'products/book_detail.html', context)