使用
Entry.objects.latest('created_at')
我可以恢复所有Entry对象的最新Entry。 但是如何获取每个用户的最新条目呢?这类似于 SQL 最新记录查询。如何使用 ORM 实现这一目标?这是我的方法,我想知道这是否是做我想做的事情的最有效的方法:
首先,我执行子查询:对象按用户分组,并为每个用户返回 Max(最新)
created_by
字段 (created_at__max
)。然后,我根据子查询中的结果过滤 Entry 对象并获取所需的对象。
Entry.objects.filter(
created_at__in=Entry.objects.values('user')
.annotate(Max('created_at'))
.values_list('created_at__max'))
或使用经理:
class UsersLatest(models.Manager):
def get_query_set(self):
return super(UsersLatest,self).get_query_set().filter(created_at__in=self.model.objects.values('user').annotate(Max('created_at')).values_list('created_at__max'))
有没有更有效的方法?可能没有子查询?
查询集的设计取决于您计划使用它的用途。我不知道为什么你要在最后使用 value_list 方法来突破 QuerySet 迭代器。我想您有一个用户状态列表,其中根据该条目模型显示上次活动时间。为此,您可能想尝试一下:
Users.objects.all().annotate(latest_activity=Max('entries__created_at'))
然后在模板中轻松循环用户
{% for user in users %}
{{ user.full_name }}
{{ user.latest_activity|date: "m/d/Y" }}
{% endfor %}
原始 SQL 是
SELECT entry.id, entry.title, entry.content, entry.user_id, entry.created_at
FROM
entry
WHERE
entry.created_at = ( SELECT Max(e2.created_at) from entry as e2 where e2.user_id = entry.user_id )
因此,一种选择是使用
where
修饰符的 extra()
参数:
Entry.objects.extra(where='entry.created_at = ( SELECT Max(e2.created_at) from entry as e2 where e2.user_id = entry.user_id )')
当然,您可能必须将
entry
更改为数据库中表的实际名称。假设您看起来很舒服 ._meta
,您可以尝试以下操作:
Entry.objects.extra( where=
'%(table)s.created_at = ( SELECT Max(e2.created_at) from %(table)s as e2 where e2.user_id = %(table)s.user_id )' % { 'table':Entry._meta.db_table }
)
可能有一种更优雅的方式来获取表的名称。
我遇到了类似的问题并这样做了:
priorities = obj.books_set.values('category').annotate(priority=Max('priority'))
注意:我将最大优先级注释为优先级,因为我将重用输出作为过滤条件。
这是具有最低优先级的类别列表。然后我这样做:
>>> priorities[0]
{'category': 1, 'priority': 10}
我想查找列表中具有类别和优先级对的书籍。最后查询集条件应该如下所示:
Q(priorities[0]) | Q(priorities[1]) | ...
要在一行中执行此操作,请在
reduce
上使用 Q.__or__
:
reduce(Q.__or__, (Q(**x) for x in priorities))
我知道它比原始 SQL 差一点,但更安全。如果您使用此代码,请注释它,因为它很难阅读。
我无法想出一个原始的 sql 查询来获取您需要的集合,所以我怀疑是否可以用这些结果构造一个 QuerySet。