加入Django ORM中的子查询

时间:2014-07-14 14:27:30

标签: sql django django-orm

我想使用Django的ORM运行一个过滤器,这样我就可以获得每个用户最近会话的一组不同用户。我设置了表格,以便user有许多sessions;有一个UserSession模型,Session模型的user = models.ForeignKey(User)模型为Users.objects.distinct('username').order_by('session__last_accessed')

到目前为止我尝试的是session.last_accessed,但我知道这不会起作用,因为Django会将select user.username, sub_query.last_accessed from ( select user_id, max(last_accessed) as last_accessed from session group by user_id ) sub_query join user on user.id = sub_query.user_id order by sub_query.last_accessed desc limit 5 列放入选择中,因此它会被选中。例如,返回5个具有5个不同会话的重复用户名,而不是单个最近会话和用户。

是否可以通过Django的ORM查询?

编辑:好的,经过一些SQL测试后我发现我想要使用的SQL是:

sub_query

我可以通过Session.objects.values('user').annotate(last_accessed=Max('last_accessed'))进行sub_query。如何使用此{{1}}来获取ORM所需的数据?

编辑2:具体来说,我想通过仅执行一个查询来执行此操作,就像上面的SQL一样。当然,我可以查询两次并在Python中进行一些处理,但是在使用ORM时我更喜欢使用数据库一次。

2 个答案:

答案 0 :(得分:1)

如果您使用的是mysql后端,则以下解决方案非常有用:

users_in_session = Session.objects.values_list('user_id', flat=True)
sessions_by_the_user_list = Session.objects \
                            .filter(user__in=set(users_in_session)) \
                            .order_by('last_accessed').distinct()

如果您使用sub_query,那么order_by('last_accessed')函数应该足以在有序列表中获取数据。虽然据我测试,这些结果似乎不稳定。

更新

您可以尝试:

Session.objects.values('user') \
  .annotate(last_accessed=Max('last_accessed')) \
  .orde‌​r_by('last_accessed').distinct()

答案 1 :(得分:0)

调用distinct('用户名')不应该返回重复的用户名。你确定你使用的是支持.dictinct(字段)的Django版本,那是Django版本的1.4之后的版本吗?在Django 1.4之前.distinct(字段)被oRM接受,但它实际上没有进行正确的DISTINCT ON查询。

另一个暗示事情没有按预期工作的是.distinct(用户名).order_by(session__last_accessed)不是有效查询 - order_by应该有用户名作为第一个参数,因为order_by必须以.distinct()调用中的字段名称。有关详细信息,请参阅https://docs.djangoproject.com/en/1.4/ref/models/querysets/#django.db.models.query.QuerySet.distinct