Django中日期处理注意事项与自定义时间格式转换详解


Posted in Python onAugust 06, 2018

前言

我们在用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有关):

![可能的默认日期格式](http://i2.51cto.com/images/blog/201803/23/164dc709843a56536c09c9142775a553.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

如果不习惯这种格式,自己定义显示格式的配置如下,更改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>;

Django中日期处理注意事项与自定义时间格式转换详解

Django中日期处理注意事项与自定义时间格式转换详解

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

相关文档:

https://docs.djangoproject.com/en/2.0/ref/settings/

https://docs.djangoproject.com/en/2.0/ref/templates/builtins/#std:templatefilter-date

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python异步任务队列示例
Apr 01 Python
深入剖析Python的爬虫框架Scrapy的结构与运作流程
Jan 20 Python
numpy中索引和切片详解
Dec 15 Python
Python利用字典将两个通讯录文本合并为一个文本实例
Jan 16 Python
Python实现字典按key或者value进行排序操作示例【sorted】
May 03 Python
Python任意字符串转16, 32, 64进制的方法
Jun 12 Python
在Pytorch中使用样本权重(sample_weight)的正确方法
Aug 17 Python
python实现对变位词的判断方法
Apr 05 Python
python3 logging日志封装实例
Apr 08 Python
python3中datetime库,time库以及pandas中的时间函数区别与详解
Apr 16 Python
查看已安装tensorflow版本的方法示例
Apr 19 Python
python Timer 类使用介绍
Dec 28 Python
python 地图经纬度转换、纠偏的实例代码
Aug 06 #Python
Anaconda下配置python+opencv+contribx的实例讲解
Aug 06 #Python
Django添加sitemap的方法示例
Aug 06 #Python
python中scikit-learn机器代码实例
Aug 05 #Python
解决使用pycharm提交代码时冲突之后文件丢失找回的方法
Aug 05 #Python
Python字符串、整数、和浮点型数相互转换实例
Aug 04 #Python
python与caffe改变通道顺序的方法
Aug 04 #Python
You might like
PHP 的几个配置文件函数
2006/12/21 PHP
PHP调用Linux的命令行执行文件压缩命令
2013/01/27 PHP
php 微信开发获取用户信息如何实现
2016/12/13 PHP
PHP将字符串首字母大小写转换的实例
2017/01/21 PHP
php实现连接access数据库并转txt写入的方法
2017/02/08 PHP
PHP安装扩展mcrypt以及相关依赖项深入讲解
2021/03/04 PHP
简单实用的js调试logger组件实现代码
2010/11/20 Javascript
js加入收藏夹代码(兼容ie/ff/op)
2014/05/16 Javascript
js实现的点击div区域外隐藏div区域
2014/06/30 Javascript
nodejs中使用monk访问mongodb
2014/07/06 NodeJs
jquery实现简洁文件上传表单样式
2015/11/02 Javascript
基于jQuery和CSS3制作数字时钟附源码下载(jquery篇)
2015/11/24 Javascript
Servlet实现文件上传,可多文件上传示例
2016/12/05 Javascript
javascript动画系列之模拟滚动条
2016/12/13 Javascript
require.js与bootstrap结合实现简单的页面登录和页面跳转功能
2017/05/12 Javascript
浅谈jQuery框架Ajax常用选项
2017/07/08 jQuery
bootstrap table插件的分页与checkbox使用详解
2017/07/23 Javascript
Vue 表单控件绑定的实现示例
2017/08/11 Javascript
javascript帧动画(实例讲解)
2017/09/02 Javascript
Vue动态修改网页标题的方法及遇到问题
2019/06/09 Javascript
Layui实现数据表格中鼠标悬浮图片放大效果,离开时恢复原图的方法
2019/09/11 Javascript
jQuery 移除事件的方法
2020/06/20 jQuery
浅谈python爬虫使用Selenium模拟浏览器行为
2018/02/23 Python
python pandas读取csv后,获取列标签的方法
2018/11/12 Python
Python简单基础小程序的实例代码
2019/04/28 Python
使用Python文件读写,自定义分隔符(custom delimiter)
2020/07/05 Python
Python selenium如何打包静态网页并下载
2020/08/12 Python
基于python模拟bfs和dfs代码实例
2020/11/19 Python
八一慰问活动方案
2014/02/07 职场文书
产品开发计划书
2014/04/27 职场文书
2014年幼儿园后勤工作总结
2014/11/10 职场文书
2014年财务经理工作总结
2014/12/08 职场文书
同学会邀请函模板
2015/01/30 职场文书
班主任开场白
2015/06/01 职场文书
雷锋的观后感
2015/06/10 职场文书
VW、VH适配移动端的解决方案与常见问题
2023/05/21 HTML / CSS