让我们假设我想显示按最新Sprint时间排序的跑步者列表。Django:根据最新的子模型字段排序QuerySet
class Runner(models.Model):
name = models.CharField(max_length=255)
class Sprint(models.Model):
runner = models.ForeignKey(Runner)
time = models.PositiveIntegerField()
created = models.DateTimeField(auto_now_add=True)
这是什么,我会在SQL做一个速写:
SELECT runner.id, runner.name, sprint.time
FROM runner
LEFT JOIN sprint ON (sprint.runner_id = runner.id)
WHERE
sprint.id = (
SELECT sprint_inner.id
FROM sprint as sprint_inner
WHERE sprint_inner.runner_id = runner.id
ORDER BY sprint_inner.created DESC
LIMIT 1
)
OR sprint.id = NULL
ORDER BY sprint.time ASC
的Django QuerySet documentation状态:
这是允许指定一个多值字段订购结果 由(例如,ManyToManyField字段)。通常这不会是一个明智的事情,它确实是一种高级使用功能。 但是,如果您知道您的查询集的筛选或可用数据 意味着您所选择的主要项目中每个 只有一个排序数据块,那么排序可能恰好是您想要执行的操作的 。谨慎使用多值字段排序和 确保结果符合您的期望。
我想我需要在这里应用一些过滤器,但我不知道究竟是什么Django的期望......
一个说明,因为它不是在这个例子明显:亚军表将有几个一百个条目,冲刺也将有几百个,并在稍后几天可能有几千条。数据将显示在分页视图中,因此Python中的排序不是一种选择。
我看到的唯一的另一种可能性是自己编写SQL,但我想不惜一切代价避免这种情况。
这不会造成相对较高的内存使用量吗?据我所知,它至少将每个跑步者都拉进记忆中,并建立一个相当大的冲刺ID列表。在数据库中有几百名跑步者的每个页面视图中进行此操作,都会让我感觉不舒服。我猜,这是缓存开始的地方。 – Strayer 2013-03-04 12:29:19
经过10000人的测试后,它使用的RAM少于10MB(实际上是3MB)。如果你认为你需要的不仅仅是这些,你应该使用原始SQL。与往常一样,最好的方法是首先进行分析 - 而不是推测。不成熟的优化和所有...... – Matt 2013-03-04 16:28:00
而且,几百条记录确实不是很多...肯定不足以担保性能优化。几十万条记录通常是你开始思考它的地方,即使这样,通常也不是什么问题(折腾成一两个索引并解决)。 – Matt 2013-03-04 16:42:55