Django ManyToMany 模板渲染与性能问题
我有一个Django模型,它里面有一种多对多的关系,具体是这样的,
class MyModel(models.Model):
name = ..
refby = models.ManyToManyField(MyModel2)
..
class MyModel2(..):
name = ..
date = ..
我需要在我的模板中展示所有与mymodel相关的mymodel2对象。目前,我的做法是这样的,
{% for i in mymodel_obj_list %}
{{i.name}}
{% for m in i.refby.all|dictsortreversed:"date"|slice:"3" %}
{{.. }}
{% endfor %}
<div> <!--This div toggles hidden/visible, shows next 12-->
{% for n in i.refby.all|dictsortreversed:"date"|slice:"3:15" %}
{{.. }}
{% endfor %}
</div>
{% endfor %}
正如代码所示,我只想显示最新的3个mymodel2对象,并且按照日期倒序排列,虽然实际上会加载接下来的12个。
这样做效率会很低吗?(考虑到refby.all的结果可能有几百个,而“mymodel_obj_list”的总结果也是几百个 - 我在这里使用了分页器)。
那么,预先计算这些refby并将它们渲染到模板的最佳方法是什么呢?我应该在视图中进行排序和计算,然后再传递过去吗?我不太确定这样做是否能保持我的分页功能。
视图代码大致是这样的,
obj_list = Table.objects.filter(..) # Few 100 records
pl = CustomPaginatorClass(obj_list...)
然后我将pl作为mymodel_obj_list传递给页面。
谢谢!
2 个回答
0
我应该在视图中进行排序和计算,然后再传递吗?
是的,绝对应该。
这其实不是性能的问题(因为Django的查询集是懒加载的,我觉得最终的性能在这两种情况下可能差不多),而是代码组织的问题。
模板不应该包含任何业务逻辑,只需要负责展示内容。当然,有时候这个原则会被打破,但一般来说,你应该尽量朝这个方向努力。
4
我假设 mymodel_obj_list
是一个查询集(QuerySet)。在循环中你访问了一个外键字段,这意味着默认情况下,Django 会一个一个地查找每个对象的引用。当你要显示很多行数据时,这样做会非常慢。
你可以在查询集上调用 select_related,这样可以提前把所有这些外键字段都拉取进来。
https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related