Django 聚合字段,但按日期过滤

Django aggregate field, but filtered by date

我正在尝试注释另一个模型的总和,但按日期过滤了。

我有模型 EmployeeShiftShift 有一个名为 dur 的 DecimalField,一个 DateTimeField start 和一个外键员工.

class Employee(models.Model):
    name = models.CharField(max_length=64)

class Shift(models.Model):
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    start = models.DateTimeField()
    dur = models.DecimalField(max_digits=4, decimal_places=2, default=0)

使用 Employee.objects.all().annotate(Sum('shift__dur')) 我可以添加所有班次的总和,但是 我如何过滤这些班次,例如仅对给定日期范围内的班次求和?

提前致谢!

您可以过滤例如:

Employee.objects.filter(
    <strong>shift__start__range=('2022-01-01', '2022-01-31')</strong>
).annotate(
    <strong>total=Sum('shift__dur')</strong>
)

这只会显示 2022 年 1 月 的班次。此外,2022 年 1 月 没有任何班次的 Employee 将被过滤掉。

您还可以获得每周的数据,例如:

from django.db.models.functions import TruncWeek

Shift.objects.values(
    'employee_id',
    <strong>week=TruncWeek('start')</strong>
).annotate(
    <strong>total=Sum('dur')</strong>
).order_by('employee_id', 'week')

这将构造一个 QuerySet 具有:

<QuerySet [
    {'employee_id': 1, 'week': date(2022, 1, 3), 'total': Decimal('14.25')},
    {'employee_id': 1, 'week': date(2022, 1, 10), 'total': Decimal('13.02')},
    {'employee_id': 1, 'week': date(2022, 1, 17), 'total': Decimal('17.89')},
    {'employee_id': 2, 'week': date(2022, 1, 3), 'total': Decimal('57.3')},
    {'employee_id': 2, 'week': date(2022, 1, 17), 'total': Decimal('18.30')}
]>

因此,这使得每个员工的主键和每周(该周被截断为从星期一开始)进行聚合,并且总计列出了 dur 班次的总数。如果对于给定的 employee_id-week 组合,没有移位,那么这将 not 出现在查询集中。因此,如果您想在这几周内引入零,则需要做一些 post-processing。