从多个模型中获取信息时优化 django 查询
Posted
技术标签:
【中文标题】从多个模型中获取信息时优化 django 查询【英文标题】:Optimise django query when fetching information from multiple models 【发布时间】:2020-10-17 21:54:19 【问题描述】:我是 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 %
【问题讨论】:
【参考方案1】:您可以使用.select_related(…)
[Django-doc] 获取publisher
、author
和bookdetail
。我们可以使用prefetch_related
def get_book_details(request, book_id, slug):
book = Book.objects.select_related(
'publisher', 'author', 'bookdetail'
).prefetch_related(
'bookprice_set', 'bookprice_set__book_type'
).get(id=book_id, slug=slug)
context = 'book': book
return render(request, 'products/book_detail.html', context)
【讨论】:
您好,谢谢您的回答。我在我的代码中尝试过它,你知道它就像一个魅力,靶心!!!使用您的代码或建议,我只需 3 次数据库查询就能够获得相同的结果。非常感谢你,我真的很感谢你的帮助。你让我开心!!!以上是关于从多个模型中获取信息时优化 django 查询的主要内容,如果未能解决你的问题,请参考以下文章