gpt4 book ai didi

django - 排除 Django 中的一行重复行

转载 作者:行者123 更新时间:2023-12-02 09:28:54 24 4
gpt4 key购买 nike

我有一个像这样的模型(简化):

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 的行。

请注意,如果存在具有相同日期和 moment_nr 且 is_group_moment=False 的行,我只想排除带有 is_group_moment=True 的行。

我尝试使用 annotate() 和 group_by() 来获取重复的行,但这只给了 med 每个重复行集中的一个,而不是我想要的两者。

例如:

╔════════════════════════════════════════╗
║ 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 的训练时刻,也是链接到特定组的多对多字段)。如果运动员计划在他也有集体时刻的第 nr 和日期的集体时刻,则他自己的时刻应优先于该时刻。

一个实用的、非常简单的例子

我有以下个人时刻:一天,一刻星期一 1星期二 1

以及以下小组时刻:一天,一刻星期二 1星期三 1

在显示时刻和与这些时刻相关的总事件的表格中,我想显示周一和周二的个人时刻,以及周三的团体时刻,因为那里没有个人时刻覆盖团体时刻。我可以使用纯 python 代码在 View 中进行求和,通过对时刻进行逐一求和,同时检查同一日期的时刻是否同时存在组时刻和单独时刻,但这将是一种非常丑陋且缓慢的方法它,特别是在总结全年时。

我尝试过的

我已经尝试过这个:

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)

这已经很接近了。这样我就可以为每个“时间段”获得一个时刻(其中团体时刻和个人时刻的时刻编号和日期相同)。问题是我需要获得两个“碰撞”时刻。然后,我可以从结果查询集中排除组时刻,并最终在对我的应用程序中的训练时刻进行求和时排除时刻。

moments_to_exclude = moments_to_exclude.exclude(is_group_moment=True)
desired_result = training_moments.exclude(pk__in=moments_to_exclude)

最佳答案

像这样

TrainingMoment.objects.filter(date=… , moment_nr=…).exclude(is_group_moment=True)

我建议您阅读 django 文档中有关模型 API 的一些内容,并使用 manage.py shell

编辑

所以这可能不是完美的解决方案,但它肯定是您想要的方向。您需要的是将其分为两个类别:Moment 和 Trainee。受训者暂时将拥有一个 bool 字段和一个外键。

class Moment(models.Model):
date = …
number = …

class Trainee(models.Model):
is_group = models.BooleanField()
moment = models.ForeignKey(Moment)

您在这里获得的是,没有具有相同日期+数字字段的重复 Moment 对象,因此更容易过滤范围,而不会太麻烦。同时,对真实值进行过滤更容易(使用方法进行),并且您可以根据客户规模进行过滤(甚至只需检查相关受训者的数量)。

您必须添加自定义约束以防止添加具有相同信息的对象,但这并不是很复杂

编辑2

为了回答您的评论,让我们以您的示例表为例。假设您当前的布局如下所示:

╔════════════════════════════════════════╗
║ 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 ║
╚════════════════════════════════════════╝

然后根据我的设计建议,它看起来像这样:

╔════════════════════════════════════════╗
║ date moment_nr related trainees ║
╠════════════════════════════════════════╣
║ 2013-10-01 1 True ║
║ 2013-10-02 1 True, False ║
║ 2013-10-03 1 False ║
║ 2013-10-03 2 False ║
║ 2013-10-04 2 True, False ║
╚════════════════════════════════════════╝

因为现在您没有重复的行,即它实际上会将早期设计中的两个 Moment 对象合并为一个具有两个相关 Trainee 对象的对象。

换句话说,问题末尾的最终代码将如下所示:

# 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))

# 3. Use the resulting queryset (tms_for_summing) to sum activity
summed_activity = Activity.objects.filter(trainingmoment__in = tms_for_summing)

坦率地说,也可以缩减为一行:

summed = Activity.objects.filter(trainingmoment__range=(start_date, end_date))

关于django - 排除 Django 中的一行重复行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19492179/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com