oma*_*mat 5 django django-orm django-aggregation
我试图根据两个DateTimeFields的时间差来获取帖子,例如,在发布后不到 10 分钟内删除的帖子。
class Post(models.Model):
...
time_posted = models.DateTimeField()
time_deleted = models.DateTimeField(blank=True, null=True)
Run Code Online (Sandbox Code Playgroud)
有了上面的模型,我试过了;
from datetime import timedelta
Post.objects.exclude(deleted__isnull=True).annotate(
delta=F('time_deleted') - F('time_posted')
).filter(delta__lt=timedelta(minutes=10))
Run Code Online (Sandbox Code Playgroud)
并得到了一个TypeError: expected string or buffer. 然后我认为这可能是类型的变化(DateTime 对象产生 Time 对象)所以我尝试了ExpressionWrapper:
Post.objects.exclude(deleted__isnull=True).annotate(
delta=models.ExpressionWrapper(
F('time_deleted') - F('time_posted'),
output_field=models.TimeField())
).filter(delta__gt=timedelta(minutes=10))
Run Code Online (Sandbox Code Playgroud)
但这也导致了同样的异常。
任何帮助深表感谢。
编辑
根据@ivan 的建议,我DurationField()改为尝试。我不再遇到异常,但 delta 总是0.
>>> post = Post.objects.exclude(deleted__isnull=True).annotate(
delta=ExpressionWrapper(F('deleted') - F('time'),
output_field=DurationField())
).first()
>>> post.time_posted
datetime.datetime(2015, 8, 24, 13, 26, 50, 857326, tzinfo=<UTC>)
>>> post.time_deleted
datetime.datetime(2015, 8, 24, 13, 27, 30, 521569, tzinfo=<UTC>)
>>> post.delta
datetime.timedelta(0)
Run Code Online (Sandbox Code Playgroud)
kwargoutput_field应该是DurationField相反的,因为它存储datetime.timedelta在 Django 中,而TimeField存储datetime.time.
但有一个警告:
在大多数情况下,使用 DurationField 进行算术是有效的。但是,在除 PostgreSQL 之外的所有数据库上,将 DurationField 的值与 DateTimeField 实例上的算术进行比较将无法按预期进行。
在 SQLite 后端中由存储微秒DurationField表示:bigint
class DatabaseWrapper(BaseDatabaseWrapper):
vendor = 'sqlite'
# ...
data_types = {
# ...
'DecimalField': 'decimal',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
# ...
}
Run Code Online (Sandbox Code Playgroud)
因为您使用的是 SQLite,所以您实际上需要delta以微秒为单位的值。请参阅此答案以了解Func它的作用。
| 归档时间: |
|
| 查看次数: |
2023 次 |
| 最近记录: |