【问题标题】:Django model elapsed time between two DateTimeFields两个 DateTimeFields 之间的 Django 模型经过的时间
【发布时间】:2019-08-04 15:55:25
【问题描述】:

我对 django 还是很陌生,并且无法找到一种方法来获取两个 DateTimeFields 之间的经过时间并将其保存到另一个模型中。

from django.db import models



class Timesheet(models.Model):
    startTime = models.DateTimeField(auto_now_add=True)
    endTime = models.DateTimeField(blank=True, null=True)
    duration = models.DateTimeField(endTime - startTime)

    def _str_(self):
        return self.startTime

如何使持续时间 = endTime - startTime? 我也在使用 PostgreSQL 数据库。

【问题讨论】:

  • 你的意思是你需要duration = endTime - startTime

标签: django python-3.x django-models


【解决方案1】:

我不会在持续时间内使用专用的模型字段。

我会使用模型上的属性来代替相同的功能。

类似:

@property
def duration(self)
    return self.end_time - self.startime

Lucas 有一个使用注释的好主意,但是如果您在某个地方有一个 Timesheet 实例,该实例不是来自该对象管理器并且之前没有注释,那么您将不得不执行单独的数据库命中来实际注释它。

这个属性是这样使用的:

some_timesheet_instance.duration

【讨论】:

    【解决方案2】:

    使用annotate() 在查询时为查询集中的每个对象计算duration 字段

    from django.db.models import F, ExpressionWrapper, fields    
    
    timesheets = Timesheet.objects.annotate(
        duration=ExpressionWrapper(
            F('endTime') - F('startTime'),
            output_field=fields.DurationField()
        )
    )
    
    timesheets[0].duration  # datetime.timedelta(0, 722, 18373)
    

    是否可以对 filter()order_by()aggregate() 等注解执行其他查询集方法。

    timesheets.order_by('-duration')  
    timesheets.aggregate(Avg('duration')) # {'duration__avg': datetime.timedelta(0, 26473, 292625)} 
    

    【讨论】:

    • 我在哪里放置此代码?如果我将它放入我的 models.py 中,我会收到一条错误消息,提示尚未加载模型。这是我的观点还是我错过了什么?
    • 此代码必须在执行查询时执行(不要放入您的models.py),duration 字段将在查询时添加
    【解决方案3】:
    duration = timesheet.end_time - timesheet.start_time
    

    当您减去两个日期时间实例时,您不会得到另一个日期时间实例,而是一个timedelta 实例,这只是两个日期时间之间的天数、秒数和微秒差异。您不能在 DateTimefield 中存储 timedelta,但可以使用 IntegerField,例如:

    days_in_seconds = duration.days * 86400   # days difference by seconds in a day
    duration_in_seconds = duration.seconds + days_in_seconds  # duration in seconds
    

    当您想以 timedelta 形式访问持续时间时,您只需这样做:

    import datetime
    
    duration = datetime.timedelta(seconds=timesheet.duration)
    

    您也可以按照 question 中的建议将其存储为 FloatField。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多