Django中的日期处理注意事项和自定义时间格式转换

栏目: Python · 发布时间: 7年前

内容简介:我们在用Django创建models时,常常会涉及时间日期字段的处理,Django里日期相关Field有DateTimeField、DateField和TimeField三种类型,看似简单,但其中有一些容易出错的地方需要注意;另外,如果不习惯Django的默认时间格式,也可以自定义的修改。DateTimeField、DateField和TimeField,其值分别对应着Python里的datetime.datetime、datetime.date和datetime.time三个实例,这三个Field里都有

我们在用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界面效果图:

Django中的日期处理注意事项和自定义时间格式转换

点击编辑页面,会发现找不到‘更新时间’的编辑处,因为此字段是只读,且不允许手动修改,效果图如下:

Django中的日期处理注意事项和自定义时间格式转换

当页面“save”之后,再观察现在的‘更新时间’发现时间已经被修改:

Django中的日期处理注意事项和自定义时间格式转换

时间已被修改

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地址段之后保存:

Django中的日期处理注意事项和自定义时间格式转换

再次编辑

更改之后‘更新时间’并未发生改变(见下图),因为‘auto_now_add’在对象创建完成后即不再更新:

Django中的日期处理注意事项和自定义时间格式转换

时间不再变化

如何实现可编辑

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',)

那么问题来了。实际场景中,往往既希望在对象的创建时间默认被设置为当前值,又希望能在日后修改它。怎么实现这种需求呢?

django中所有的model字段都拥有一个default参数,用来给字段设置默认值。可以用default=timezone.now来替换auto_now=True或auto_now_add=True。timezone.now对应着django.utils.timezone.now(),代码示例:

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()后,再次编辑已经能看到相应‘更新时间’字段,并且可修改:

Django中的日期处理注意事项和自定义时间格式转换

更新时间已可修改

我们把时间天数加1天后,保存退出再观察‘更新时间’已经变为自定义时间:

保存后时间变为自定义时间

Django中的日期处理注意事项和自定义时间格式转换

自定义日期格式:

刚创建的Django应用,可能你看到的日期显示格式跟下图类似(跟LANGUAGE_CODE和TIME_ZONE有关):

![可能的默认日期格式]

Django中的日期处理注意事项和自定义时间格式转换

如果不习惯这种格式,自己定义显示格式的配置如下,更改Django的setting.py文件:

USE_L10N = False

DATE_FORMAT = 'Y-m-d'

DATETIME_FORMAT = 'Y-m-d H:i:s'

注意事项:如果USE_L10N设置为了True,那么语言环境规定的格式具有更高的优先级并将被应用,即DATE_FORMAT不生效。

这里可用的格式化字符串的其他写法参见Django官方文档:

< https://docs.djangoproject.com/en/2.0/ref/templates/builtins/#date >;

Available format strings,部分截图:

Django中的日期处理注意事项和自定义时间格式转换

Django中的日期处理注意事项和自定义时间格式转换

format stringsDjango中的日期处理注意事项和自定义时间格式转换

另外在Django页面渲染的时候,html页面从数据库中读出DateTimeField字段时,显示的时间格式和数据库中存放的格式不一致,另外一个解决办法:可以在页面格式化时间,添加{{ Datacenter.updatetime|date:"Y-m-d H:i:s" }}类似的过滤器。之后刷新页面,即可正常显示。


以上所述就是小编给大家介绍的《Django中的日期处理注意事项和自定义时间格式转换》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Coming of Age in Second Life

Coming of Age in Second Life

Tom Boellstorff / Princeton University Press / 2008-04-21 / USD 29.95

The gap between the virtual and the physical, and its effect on the ideas of personhood and relationships, is the most interesting aspect of Boellstorff's analysis... Boellstorff's portrayal of a virt......一起来看看 《Coming of Age in Second Life》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器