如何计算 Django 的总工作时间?

How to calculate total working hours in Django?

我创建了以下模型:

class Timesheet(models.Model):
    date = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Data")
    entry = models.TimeField(auto_now=False, auto_now_add=False, verbose_name="Hora Entrada")
    lunch = models.TimeField(auto_now=False, auto_now_add=False, null=True, blank=True, verbose_name="Início do Almoço")
    lunch_end = models.TimeField(auto_now=False, auto_now_add=False, null=True, blank=True, verbose_name="Fim do Almoço")
    out = models.TimeField(auto_now=False, auto_now_add=False, verbose_name="Hora de Saída")

然后在 table 中返回,其中有一个名为“总时数”的额外字段,我需要在其中计算总工作时数。每个条目都指同一天。

而我的看法是:

def timesheet(request):
    c = Timesheet.objects.all()
    context = {'c': c}
    return render(request, "tracker/timesheet.html", context)

我需要做的计算是:(out - entry) - (lunch_end - lunch).

我怎样才能做到这一点?

您可以 .annotate(…) [Django-doc] 每个 Timesheet 对象:

from django.db.models import DurationField, ExpressionWrapper, F, IntegerField

Timesheet.objects.annotate(
    total_time=ExpressionWrapper(
        ExpressionWrapper(F('out') - F('entry'), output_field=IntegerField()) -
        ExpressionWrapper(F('lunch_end') - F('lunch'), output_field=IntegerField()),
       output_field=DurationField()
    )
)

这里从 this 查询集产生的每个 Timesheet 对象将有一个额外的属性 .total_time,它将包含该人工作的持续时间(因此减去午休)。

或者您可以用 .aggregate(…) [Django-doc]:

对所有记录求和
from django.db.models import DurationField, ExpressionWrapper, F, IntegerField

Timesheet.objects.<b>aggregate(</b>
    total_time=<b>Sum(</b>
        ExpressionWrapper(F('out') - F('entry'), output_field=IntegerField()) -
        ExpressionWrapper(F('lunch_end') - F('lunch'), output_field=IntegerField()),
       output_field=DurationField()
    <b>)</b>
)['total_time']

如果 lunchlunch_end 可以是 None/NULL,你可以使用 Coalesce [Django-doc]:

from django.db.models import DurationField, ExpressionWrapper, F, IntegerField, Value
from django.db.models.functions import Coalesce

Timesheet.objects.<b>aggregate(</b>
    total_time=<b>Sum(</b>
        ExpressionWrapper(F('out') - F('entry'), output_field=IntegerField()) -
        Coalesce(ExpressionWrapper(F('lunch_end') - F('lunch'), output_field=IntegerField()), Value(0)),
       output_field=DurationField()
    <b>)</b>
)['total_time']

如果你因此有 .annotate(…)d 所有 Timesheet 条记录,并将它们作为 c 传递,你可以使用:

{% for ci in c %}
    {{ ci.data }}: {{ ci.entry }} - {{ ci.out }}; {{ <b>ci.</b>total_time }}
{% endfor %}