Django - 如何以有效的方式获取最新的相关模型,我可以在模板上进行迭代?
Posted
技术标签:
【中文标题】Django - 如何以有效的方式获取最新的相关模型,我可以在模板上进行迭代?【英文标题】:Django - how to obtain the latest related model in an efficent way I can iterate on the template? 【发布时间】:2021-03-14 08:52:34 【问题描述】:假设我有两个相关模型,其中一个带有日期时间字段。 (作者和书,带有 pub_date)。
我想显示作者列表和他们每个人写的最新书籍。
我在Author
模型上做了一个方法:
def get_latest_book(self):
return self.books.all().latest('pub_date')
这是可行的,但是在模板上渲染时效率非常低:
views.py:
class AuthorListView(ListView):
model = Author
template_name = 'author_list.html'
def get_queryset(self):
return self.model.objects.filter(owner=self.request.user).order_by('name').prefetch_related('books')
author_list.html:
...
% for author in author_list %
Name: author.name - Latest publication: author.get_latest_book
% endfor %
...
这会产生大量查询,例如:
SELECT ••• FROM `app_book` WHERE `app_book`.`author_id` = 374 ORDER BY `app_book`.`pub_date` DESC LIMIT 1
36 similar queries.
对于我在数据库中的每个作者! 这会导致图书列表的加载时间过长。
如何以有效的方式在模板上打印作者列表及其最新书籍?
【问题讨论】:
【参考方案1】:提高效率的一种简单方法是使用Prefetch
object [Django-doc]:
from django.db.models import Prefetch
class AuthorListView(ListView):
model = Author
template_name = 'author_list.html'
def get_queryset(self):
return self.model.objects.filter(
owner=self.request.user
).prefetch_related(
Prefetch('books', Book.objects.order_by('-pub_date'), to_attr='books_ordered')
).order_by('name')
然后使用:
% for author in author_list %
Name: author.name - Latest publication: author.books_ordered.0
% endfor %
然而,这会将所有相关书籍加载到内存中,但在单个查询中。
【讨论】:
感谢您的回答,它有效并减少了我的查询和加载时间。我唯一不清楚的是您的最后一句话:在单个查询中加载内存中的所有相关项目是一件坏事吗?为了获得最佳性能,我应该更喜欢使用什么? @Willem ,你怎么看这个:Book.objects.all().order_by('author', '-pubdate').distinct('author') 除非它不起作用如果数据库不接受不同的? @EricMartin:据我所知,Django 仅对 PostgreSQL 数据库执行此操作(这可能是唯一支持此操作的数据库),但此外它不包括Author
s还没有出版任何书。以上是关于Django - 如何以有效的方式获取最新的相关模型,我可以在模板上进行迭代?的主要内容,如果未能解决你的问题,请参考以下文章
使用 django ORM 获取只有最新孩子的父母的优化方式
Django admin自定义字段按条件获取最新相关对象的结果
快速获取最新股票相关数据,并使用数据分析进行数据清洗,获取有效信息
如何获取用户在 SQL 或 Ruby 中评论的页面上的最新评论?
如何识别 ReCaptcha V2 的 32 位数据站点密钥以使用 Selenium 和 Python 请求以编程方式获取有效响应?