我很惊讶这个问题没有出现。在网上找不到多少。
使用Entry.objects.latest('created_at')
我可以恢复所有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'))
有更有效的方法吗?可能没有子查询?
谢谢,
保
答案 0 :(得分:4)
Entry.objects.all().order_by('user', 'created_at').distinct('user')
然后在'user'和'created_at'字段中将性能添加到一起。
但我认为真正的制作方式是使用Redis
来缓存和更新id的最新用户条目列表。
答案 1 :(得分:1)
QuerySet的设计取决于您打算使用它的目的。我不确定你为什么要在最后使用values_list方法打破QuerySet迭代器。我想你有一个用户状态列表,你可以根据那个Entries模型显示最后的活动时间。为此您可能想尝试这个:
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 %}
答案 2 :(得分:1)
原始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 )
所以一个选项是使用extra()
modifier的where
参数:
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 }
)
可能有一种更优雅的方式来获取表格的名称。
答案 3 :(得分:0)
我遇到了类似的问题并且这样做了:
priorities = obj.books_set.values('category').annotate(priority=Max('priority'))
注意:我将最高优先级注释为优先级,因为我将重复使用输出作为过滤条件。
这是一个具有最低优先级的类别列表。然后我这样做:
>>> priorities[0]
{'category': 1, 'priority': 10}
我想找到有类别和类别的书籍。列表中的一个优先级对。最后,queryset条件应如下所示:
Q(priorities[0]) | Q(priorities[1]) | ...
要在一行中执行此操作,请在reduce
上使用Q.__or__
:
reduce(Q.__or__, (Q(**x) for x in priorities))
我知道它比原始SQL更糟糕,但更安全。如果您使用它,请注释此代码,因为它很难阅读。
答案 4 :(得分:-1)
我想不出一个原始的sql查询会获取你需要的集合,所以我怀疑用这些结果构造一个QuerySet是可能的。