前言
我们在用Django创建models时,常常会涉及时间日期字段的处理,Django里日期相关Field有DateTimeField、DateField和TimeField三种类型,看似简单,但其中有一些容易出错的地方需要注意;另外,如果不习惯Django的默认时间格式,也可以自定义的修改。
DateTimeField、DateField和TimeField,其值分别对应着Python里的datetime.datetime、datetime.date和datetime.time三个实例,这三个Field里都有两个参数:auto_now和auto_now_add,默认值均为False。
auto_now参数说明:
每次保存对象时自动将字段值设置为当前时间,能够在保存该字段时,将其值设置为当前时间,并且每次修改model,都会自动更新。因此这个参数在需要存储“最后修改时间”的场景下,十分方便,常用类似“last-modified”或者"update_time"字段。
需要注意的是,该字段不能被手动修改覆盖;当设置为true时,只有每次调用Model.save()时,才会强制更新为当前时间点;当用其他方式更新其他字段时并不会更新:比如用QuerySet.update()方法,即使为该字段指定一个自定义的值,该字段也不会有所更改。比较直观的表现形式是,如果使用django自带的admin管理器,那么该字段在admin中是只读的,并且无法进行修改。
示例代码如下:
class Datacenter(models.Model): id = models.UUIDField('机房ID', default=uuid.uuid4, primary_key=True) zone = models.ForeignKey(Zone, verbose_name='所在区域', on_delete=models.PROTECT) dc_name = models.CharField('机房', max_length=128, unique=True) networks = models.CharField('IP地址段', max_length=128, blank=True, unique=True) update_time = models.DateTimeField('更新时间', auto_now=True) def __str__(self): return self.dc_name class Meta: verbose_name = '机房配置' verbose_name_plural = '机房配置'
Datacenter的ModelAdmin代码:
class DatacenterAdmin(admin.ModelAdmin): list_display = ['id', 'dc_name', 'zone', 'networks', 'update_time'] search_fields = ['dc_name', 'zone', 'networks'] list_filter = ['dc_name', 'zone'] ordering = ['networks', 'zone'] admin.site.register(models.Datacenter, DatacenterAdmin)
Admin界面效果图:
点击编辑页面,会发现找不到‘更新时间'的编辑处,因为此字段是只读,且不允许手动修改,效果图如下:
当页面“save”之后,再观察现在的‘更新时间'发现时间已经被修改:
auto_now_add参数说明:
设置为True时,会在model对象第一次被创建时,将字段的值设置为创建时的时间,以后修改对象时,字段的值不会再更新。该属性通常被用在存储“创建时间”的场景下。与auto_now类似,auto_now_add也具有强制性,一旦被设置为True,就无法在程序中手动为字段赋值,在admin中字段也会成为只读的。
继续沿用刚才的代码示例,'update_time'的'auto_now'改完'auto_now_add',其他代码不变:
class Datacenter(models.Model): id = models.UUIDField('机房ID', default=uuid.uuid4, primary_key=True) zone = models.ForeignKey(Zone, verbose_name='所在区域', on_delete=models.PROTECT) dc_name = models.CharField('机房', max_length=128, unique=True) networks = models.CharField('IP地址段', max_length=128, blank=True, unique=True) update_time = models.DateTimeField('更新时间', auto_now_add=True)
编辑更新北京联通机房的IP地址段之后保存:
更改之后‘更新时间'并未发生改变(见下图),因为‘auto_now_add'在对象创建完成后即不再更新:
如何实现可编辑
auto_now和auto_now_add被设置为True后,这样做会导致字段成为editable=False和blank=True的状态。editable=False将导致字段不会被呈现在admin中,blank=Ture表示允许在表单中不输入值。此时,如果在admin的fields或fieldset中强行加入该日期时间字段,那么程序会报错,admin无法打开;如果在admin中修改对象时,想要看到日期和时间,可以将日期时间字段添加到admin类的readonly_fields中:
readonly_fields = ('save_date', 'mod_date',)
那么问题来了。实际场景中,往往既希望在对象的创建时间默认被设置为当前值,又希望能在日后修改它。怎么实现这种需求呢"htmlcode">
from django.utils import timezone class Datacenter(models.Model): id = models.UUIDField('机房ID', default=uuid.uuid4, primary_key=True) zone = models.ForeignKey(Zone, verbose_name='所在区域', on_delete=models.PROTECT) dc_name = models.CharField('机房', max_length=128, unique=True) networks = models.CharField('IP地址段', max_length=128, blank=True, unique=True) update_time = models.DateTimeField('更新时间', default=timezone.now()) def __str__(self): return self.dc_name class Meta: verbose_name = '机房配置' verbose_name_plural = '机房配置'
这里'update_time'字段默认值改为timezone.now()后,再次编辑已经能看到相应‘更新时间'字段,并且可修改:
我们把时间天数加1天后,保存退出再观察‘更新时间'已经变为自定义时间:
自定义日期格式:
刚创建的Django应用,可能你看到的日期显示格式跟下图类似(跟LANGUAGE_CODE和TIME_ZONE有关):
,光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]