创建一个辅助函数,用于从任何查询集中安全地提取“顶部”项。我在自己的 Django 应用程序中到处使用它。
def top_or_none(queryset):
"""Safely pulls off the top element in a queryset"""
# Extracts a single element collection w/ top item
result = queryset[0:1]
# Return that element or None if there weren't any matches
return result[0] if result else None
这使用了一些技巧切片运算符在 SQL 中添加限制子句 http://docs.djangoproject.com/en/dev/topics/db/queries/#id4.
现在,您可以在任何需要获取查询集“顶部”项的地方使用此函数。在这种情况下,您想要获取给定 A 的顶部 B 项,其中 B 按 pk 降序排序,如下所示:
latest = top_or_none(B.objects.filter(a=my_a).order_by('-pk'))
最近还添加了“Max”功能Django聚合 http://docs.djangoproject.com/en/dev/topics/db/aggregation/这可以帮助您获得最大 pk,但我不喜欢这种情况下的解决方案,因为它增加了复杂性。
附:我真的不喜欢依赖“pk”字段来进行此类查询,因为某些 RDBMS 不保证顺序 pk 与逻辑创建顺序相同。如果我有一个我知道需要以这种方式查询的表,我通常有自己的“创建”日期时间列,我可以用它来排序而不是 pk。
根据评论进行编辑:
如果您更愿意使用 queryset[0],您可以这样修改 'top_or_none' 函数:
def top_or_none(queryset):
"""Safely pulls off the top element in a queryset"""
try:
return queryset[0]
except IndexError:
return None
我最初没有提出这个建议,因为我的印象是 queryset[0] 会拉回整个结果集,然后取出第 0 项。显然 Django 在这种情况下也添加了“LIMIT 1”,因此它是我的切片版本的安全替代方案。
Edit 2
当然,您也可以在此处利用 Django 的相关管理器构造,并根据您的偏好通过“A”对象构建查询集:
latest = top_or_none(my_a.b_set.order_by('-pk'))