如何使用 update() 在 Django 中的日期时间字段上增加年份?
Posted
技术标签:
【中文标题】如何使用 update() 在 Django 中的日期时间字段上增加年份?【英文标题】:How to increment the year on a datetimefield in Django with update()? 【发布时间】:2011-05-04 20:01:50 【问题描述】:有没有办法使用 update() 方法增加过滤对象的年份?
我正在使用:
python 2.6.5
django 1.2.1 final
mysql Ver 14.14 Distrib 5.1.41
我知道可以这样做:
today = datetime.datetime.today()
for event in Event.objects.filter(end_date__lt=today).iterator():
event.start_date = festival.start_date + datetime.timedelta(365)
event.end_date = festival.end_date + datetime.timedelta(365)
event.save()
但是,在某些情况下,我更喜欢使用 update() 方法。
# This does not work..
Event.objects.all().update(
start_date=F('start_date') + datetime.timedelta(365),
end_date=F('end_date') + datetime.timedelta(365)
)
通过上面的例子,我得到:
Warning: Truncated incorrect DOUBLE value: '365 0:0:0'
它试图进行的 sql 查询是:
UPDATE `events_event` SET `start_date` = `events_event`.`start_date` + 365 days, 0:00:00, `end_date` = `events_event`.`end_date` + 365 days, 0:00:00
我在 mysql 指南中找到了一些东西,但这是原始 sql!
SELECT DATE_ADD('2008-12-15', INTERVAL 1 YEAR);
有什么想法吗?
【问题讨论】:
好像有一张带补丁的公开票:code.djangoproject.com/ticket/10154 【参考方案1】:快速但丑陋:
>>> a.created.timetuple()
time.struct_time(tm_year=2000, tm_mon=11, tm_mday=2, tm_hour=2, tm_min=35, tm_se
c=14, tm_wday=3, tm_yday=307, tm_isdst=-1)
>>> time = list(a.created.timetuple())
>>> time[0] = time[0] + 1
>>> time
[2001, 11, 2, 2, 35, 14, 3, 307, -1]
>>>
【讨论】:
【参考方案2】:from dateutil.relativedelta import relativedelta
yourdate = datetime.datetime(2010, 11, 4, 10, 14, 54, 518749)
yourdate += relativedelta(years=+1)
Relativedelta 需要很多时间参数,从秒到年...
【讨论】:
问题不在于计算额外的年份。使用 django 更新的好处是原始日期不会从数据库中取出。您的建议类似于@louis 在他的问题顶部提出的建议 - 从数据库中取出日期,更改它并将其保存回来。这需要两个查询而不是一个。 对此感到抱歉...一种不可能的解决方案可能是使用 F 重新分配值,但我想这对于日期字段是不可能的...这是 F 的文档:docs.djangoproject.com/en/dev/topics/db/queries/… 【参考方案3】:你见过这个:Increasing a datetime field with queryset.update 吗?我还记得在 MySQL 后端成功地使用了带有 timedelta 的 queryset .update()。
【讨论】:
感谢您的建议,但我仍然收到,警告:截断不正确的 DOUBLE 值:'365 0:0:0'【参考方案4】:“警告:X 列的数据被截断” 异常的一个潜在原因是对添加到 DateField 的时间增量使用了非全天值 - 它在 python 中很好,但在写入 mysql 数据库时失败。如果您有 DateTimeField,它也可以工作,因为持久字段的精度与 timedelta 的精度相匹配。
即:
>>> from django.db.models import F
>>> from datetime import timedelta
>>> from myapp.models import MyModel
>>> [field for field in MyModel._meta.fields if field.name == 'valid_until'][0]
<django.db.models.fields.DateField object at 0x3d72fd0>
>>> [field for field in MyModel._meta.fields if field.name == 'timestamp'][0]
<django.db.models.fields.DateTimeField object at 0x43756d0>
>>> MyModel.objects.filter(pk=1).update(valid_until=F('valid_until') + timedelta(days=3))
1L
>>> MyModel.objects.filter(pk=1).update(valid_until=F('valid_until') + timedelta(days=3.5))
Traceback (most recent call last):
...
Warning: Data truncated for column 'valid_until' at row 1
>>> MyModel.objects.filter(pk=1).update(timestamp=F('timestamp') + timedelta(days=3.5))
1L
【讨论】:
以上是关于如何使用 update() 在 Django 中的日期时间字段上增加年份?的主要内容,如果未能解决你的问题,请参考以下文章
django rest框架中的save()、create()和update()有啥区别?
尝试覆盖django rest框架中的update方法,以在更新后返回整个查询集
如何将 ID 的编辑方法转移到 Django 中的按钮/链接?