优化从多个模型获取信息时的 django 查询



我是Django的新手,使用Django 3.0.6。

使用以下代码,我已经能够获得所需的结果并在模板上显示详细的书籍信息。但是,平均而言,ORM进行8到9次数据库查询以获取有关该书的详细信息。我正在寻找专家帮助来优化我的数据库查询,以便我可以用更少的查询获取与书籍相关的信息。

我尝试使用select_related()prefetch_related()但没有任何运气,也许我做得不恰当。有没有使用Q objectunion()的范围,只是我的想法?如何以最少的数据库查询获得相同的结果?

如果可能的话,请帮助我提供详细的代码。

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] 来获取publisherauthorbookdetail。我们可以使用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)

最新更新