我有这个问题:
checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location)
这对于告诉我在特定地点的日期范围内发生了多少次签到非常有用。但我想知道独特用户完成了多少次签到。所以我尝试了这个:
checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location).values('user').distinct()
但这不起作用,我得到一个空数组。有什么想法吗?
这是我的CheckinAct模型:
class CheckinAct(models.Model):
user = models.ForeignKey(User)
location = models.ForeignKey(Location)
time = models.DateTimeField()
----更新------ 所以现在我更新了我的查询,看起来像这样:
checkins = CheckinAct.objects.values('user').\
filter(time__range=[start, end], location=checkin.location).\
annotate(dcount=Count('user'))
但是我仍然得到具有相同用户的多个对象,如下所示:
[{'user': 15521L}, {'user': 15521L}, {'user': 15521L}, {'user': 15521L}, {'user': 15521L}]
----更新2 ------ 这是我尝试过的其他内容,但是当我记录checkins对象时,我仍然会收到许多相同的用户对象。
checkins = CheckinAct.objects.filter(
time__range=[start, end],
location=checkin.location,
).annotate(dcount=Count('user')).values('user', 'dcount')
logger.info("checkins!!! : " + str(checkins))
记录以下内容:
checkins!!! : [{'user': 15521L}, {'user': 15521L}, {'user': 15521L}]
注意同一个用户对象有3个实例。这是否正常工作?是否有不同的方法来读出dict对象中的内容?我只需要知道有多少唯一身份用户在该时间范围内检查该特定位置。
答案 0 :(得分:1)
答案实际上在Django docs。不幸的是,很少关注你需要的特定部分的重要性;所以这是可以理解的错过了。 (稍微阅读处理Item
s的部分。)
对于您的用例,以下内容应该为您提供您想要的内容:
checkins = CheckinAct.objects.filter(time__range=[start,end], location=checkin.location).\
values('user').annotate(checkin_count=Count('pk')).order_by()
<强>更新强>
根据你的评论,我认为你想要实现的目标一直困惑。上面的查询给出的是每个用户在某个位置签到的次数列表,该列表中没有重复的用户。现在看来,您真正想要的是在一个特定位置签入的唯一身份用户的数量。为此,请使用以下内容(无论如何都要简单得多):
User.objects.filter(checkinat__location=location).distinct().count()
非相关支持的更新
checkin_users = [(c.user.pk, c.user) for c in CheckinAct.objects.filter(location=location)]
unique_checkins = len(dict(checkin_users))
这符合dict
具有唯一键的原则。因此,当您将元组列表转换为dict时,最终会得到一个唯一用户列表。 但是,这将生成1 * N个查询,其中N是签入的总量(每次使用user
属性时一个查询。通常,我会执行类似{{{{ 1}},但是这也需要一个JOIN,显然已经出局了。如果没有,那么JOIN不受支持似乎是非强烈的巨大的缺点,但是如果是这样的话,那将会是你唯一的选择。
答案 1 :(得分:0)
您不希望DISTINCT
。你真的希望Django做一些最终会给你一个GROUP BY
条款的东西。你也是正确的,你的最终解决方案是annotate()
和values()
,正如所讨论的那样in the Django documentation。
要获得结果,您要先使用annotate
,然后使用values
,例如:
CheckinAct.objects.filter(
time__range=[start, end],
location=checkin.location,
).annotate(dcount=Count('user').values('user', 'dcount')
我上面给你的链接上的Django文档显示了一个类似构造的查询(减去filter
方面,我在适当的位置添加了你的情况),并注意到这将“现在产生一个唯一的每个[checkin act]的结果;但是,只有[user]和[dcount
]注释将在输出数据中返回“。 (我编辑了句子以适合你的情况,但原则是一样的。)
希望有所帮助!
答案 2 :(得分:0)
checkins = CheckinAct.objects.values('user').\
filter(time__range=[start, end], location=checkin.location).\
annotate(dcount=Count('user'))
如果我没有弄错,你想要的值不会作为“dcount”输入吗?因此,当您决定单独输出用户值时,是不是只是被丢弃了?
你能告诉我你在尝试时会发生什么吗?
checkins = CheckinAct.objects.values('user').\
filter(time__range=[start, end], location=checkin.location).\
annotate(Count('user')).order_by()
(最后一个order_by是为了清除你在模型级别可能已经拥有的任何内置顺序 - 不确定你是否有类似的东西,但是不会有问题......)