我有一个这样的模型(简化):
class TrainingMoment(models.Model):
date = models.DateField()
# Moment of the day, 2 is afternoon for example
moment_nr = models.IntegerField()
is_group_moment = models.BooleanField()
在给定的日期和 moment_nr 上,可以存在 2 行。一个与is_group_moment=False
一个与is_group_moment=True
。对于TrainingMoment.objects.filter(date__range=(start_date,end_date))
我想要排除的行中的每一个重复项is_group_moment = True
。
请注意,我只想排除is_group_moment=True
具有相同日期和 moment_nr 的行的行is_group_moment=False
。
我曾尝试将 annotate() 与 group_by() 一起使用来获取重复的行,但这只给了每个重复行集中的一个,而不是我想要的两个。
例如:
╔════════════════════════════════════════╗
║ date moment_nr is_group_moment ║
╠════════════════════════════════════════╣
║ 2013-10-01 1 True ║
║ 2013-10-02 1 True ║
║ 2013-10-02 1 False ║
║ 2013-10-03 1 False ║
║ 2013-10-03 2 False ║
║ 2013-10-04 2 True ║
║ 2013-10-04 2 False ║
║ 2013-10-01 1 True ║
╚════════════════════════════════════════╝
应该:
╔═════════════════════════════════════════╗
║ date moment_nr is_group_moment ║
╠═════════════════════════════════════════╣
║ 2013-10-01 1 True ║
║ 2013-10-02 1 False ║
║ 2013-10-03 1 False ║
║ 2013-10-03 2 False ║
║ 2013-10-04 2 False ║
║ 2013-10-01 1 True ║
╚═════════════════════════════════════════╝
我有另一个模型 Activity,它存储训练时间,我想使用上面的查询集来获得正确的一周总和:
class Activity(models.Model):
activitytype = models.ForeignKey(ActivityType)
trainingmoment = models.ForeignKey(TrainingMoment)
# Time in minutes
time = models.IntegerField()
我想要完成的总结:
# 1. Get training moments for a given period, for example a week (no problem here)
tms_for_summing = TrainingMoment.objects.filter(date__range=(start_date,end_date))
# 2. Filter out duplicates in the way described above
# 3. Use the resulting queryset (tms_for_summing) to sum activity
summed_activity = Activity.objects.filter(trainingmoment__in = tms_for_summing)
编辑 这里为那些想知道我的数据库设计的人提供了一些额外的解释:
正如您可能已经想到的那样,这是一个培训记录应用程序。在我的问题中,我想要实现的页面是一个计划页面。所有的训练时刻都是计划好的训练时刻。单个运动员可以计划自己的训练。此外,教练可以同时为一组运动员计划训练。这成为一个组时刻(is_groupmoment = True 的训练时刻以及链接到特定组的多对多字段)。如果运动员在他也有一个集体时刻的时刻和日期计划一个集体时刻,他自己的时刻应该覆盖这个时刻。
一个实用的、非常简单的例子
我有以下个人时刻: Day, Momentnr 星期一 1 星期二 1
以及以下集体时刻:Day, Momentnr 周二 1 周三 1
在我显示与这些时刻相关的时刻和总活动的表格中,我想显示周一和周二的个人时刻,以及周三的集体时刻,因为那里没有个人时刻超越集体时刻。我可以使用纯python代码在视图中求和,方法是对时刻进行逐个求和,同时检查同一日期是否同时存在组时刻和个人时刻,但这将是一种非常丑陋且缓慢的方法它,特别是在总结一整年时。
我试过的
我试过这个:
training_moments = TrainingMoment.objects.filter(date__range=('2013-08-19','2013-10-28'))
moments_to_exclude = training_moments.annotate(num_dates=Count('date'), num_momentnrs=Count('momentnr')).filter(num_dates__gt= 1, num_momentnrs__gt=1)
这很接近。有了这个,我为每个“时间段”得到一个时刻(其中时刻 nr 和日期对于团体时刻和个人时刻是相同的)。问题是我需要同时获得“碰撞”时刻。然后我可以从结果查询集中排除组时刻,最后在我的应用程序中总结训练时刻时排除这些时刻。
moments_to_exclude = moments_to_exclude.exclude(is_group_moment=True)
desired_result = training_moments.exclude(pk__in=moments_to_exclude)