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字符串str和字节数组相互转化方法
Mar 18 Python
python脚本替换指定行实现步骤
Jul 11 Python
python实现音乐下载器
Apr 15 Python
python框架中flask知识点总结
Aug 17 Python
详解Python连接MySQL数据库的多种方式
Apr 16 Python
使用pyinstaller打包PyQt4程序遇到的问题及解决方法
Jun 24 Python
django基于cors解决跨域请求问题详解
Aug 06 Python
基于Python和PyYAML读取yaml配置文件数据
Jan 13 Python
Python3.9又更新了:dict内置新功能
Feb 28 Python
python实例化对象的具体方法
Jun 17 Python
使用keras实现BiLSTM+CNN+CRF文字标记NER
Jun 29 Python
python如何爬取动态网站
Sep 09 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递归列出所有文件和目录的代码
2008/09/10 PHP
微信扫描二维码登录网站代码示例
2013/12/30 PHP
ThinkPHP的MVC开发机制实例解析
2014/08/23 PHP
解决laravel5中auth用户登录其他页面获取不到登录信息的问题
2019/10/08 PHP
javascript 写类方式之三
2009/07/05 Javascript
JavaScript 异步调用框架 (Part 6 - 实例 &amp; 模式)
2009/08/04 Javascript
js自定义事件及事件交互原理概述(一)
2013/02/01 Javascript
基于jquery实现的可编辑下拉框实现代码
2014/08/02 Javascript
深入分析JSON编码格式提交表单数据
2015/06/25 Javascript
Webpack 实现 Node.js 代码热替换
2015/10/22 Javascript
使用JavaScript为Kindeditor自定义按钮增加Audio标签
2016/03/18 Javascript
javascript时间差插件分享
2016/07/18 Javascript
有关文件上传 非ajax提交 得到后台数据问题
2016/10/12 Javascript
jQuery实现优雅的弹窗效果(6)
2017/02/08 Javascript
修改 bootstrap table 默认detailRow样式的实例代码
2017/07/21 Javascript
微信小程序实现选项卡功能
2020/06/19 Javascript
微信小程序canvas开发水果老虎机的思路详解
2020/02/07 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
2020/03/05 Javascript
javascript用defineProperty实现简单的双向绑定方法
2020/04/03 Javascript
基于js实现数组相邻元素上移下移
2020/05/19 Javascript
JavaScript中arguments的使用方法详解
2020/12/20 Javascript
python解析xml模块封装代码
2014/02/07 Python
Python使用openpyxl读写excel文件的方法
2017/06/30 Python
python素数筛选法浅析
2018/03/19 Python
Django rest framework实现分页的示例
2018/05/24 Python
Python创建字典的八种方式
2019/02/27 Python
详解基于python的多张不同宽高图片拼接成大图
2019/09/26 Python
python运用pygame库实现双人弹球小游戏
2019/11/25 Python
澳大利亚票务和娱乐市场领导者:Ticketmaster
2017/03/03 全球购物
Servlet都有哪些方法?主要作用是什么?
2014/03/04 面试题
高中语文教学反思
2014/01/16 职场文书
蜜蜂引路教学反思
2014/02/04 职场文书
应急处置方案
2014/06/16 职场文书
大学生个人简历自荐信
2015/03/06 职场文书
辣妈辣妹观后感
2015/06/10 职场文书
2016年春季运动会通讯稿
2015/11/25 职场文书