F()表达式的求和与由F()表达式创建的时间增量的总和

4
我的提案模型定义如下:
class Proposal(models.Model):
    scheduled_time = models.DateTimeField()
    duration = models.IntegerField() # stores minutes as an integer

    # (extra fields clipped for brevity's sake)

我希望为每个提案对象添加注释,它包括一个通过scheduled_time和表示持续时间的timedelta计算得出的“结束”日期时间,例如timedelta(minutes=duration)。然而,F()表达式似乎不能作为timedelta()函数的参数。

>>> from datetime import timedelta
>>> from django.db.models import F
>>> from schedule.models import Proposal
>>>
>>> proposals = Proposal.objects.all()
>>> annotated = proposals.annotate(
...     end=F('scheduled_time')+timedelta(minutes=F('duration')))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: unsupported type for timedelta minutes component: F
>>>

这种操作是否可以使用annotate()和F()表达式来完成? 编辑:注释的目的是为了能够在计算出的结束时间上进行过滤/排除。

看起来 F('duration') 没有返回一个数字.. (?) - Qiau
2个回答

1

F()表达式仅适用于Django(因为它们返回特定对象的实例)。您不能将它们传递给timedelta或任何其他东西,除非是Django查询集方法中的某些方法。

因此,最好向您的模型添加新字段:

class Proposal(models.Model):
    scheduled_time = models.DateTimeField()
    duration = IntegerField()
    end = models.DateTimeField(default=self.scheduled_time + timedelta(minutes=self.duration))

是的,这可能是正确的方法。我希望有人能提出一个不需要修改模型的解决方案,但我认为唯一的答案是跳过ORM并使用SQL。 - Riley Watkins
抱歉,但是这会导致NameError: name 'self' is not defined错误。请查看我的答案,可能会有可行的解决方案。 - malteo

1

F()不能像@Daniil已经指出的那样使用。

一种可能的解决方案是添加一个新字段。

end_time = models.DateTimeField()

并覆盖(save)保存方法

def save(self, *args, **kwargs):
    if not self.end_time:
        self.end_time = self.scheduled_time + datetime.timedelta(self.duration)
    super(Proposal, self).save(*args, **kwargs)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接