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

前言

我们在用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',)

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

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

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

自定义日期格式:
刚创建的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页面渲染的时候,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

总结

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

(0)

相关推荐

  • 详解Django将秒转换为xx天xx时xx分

    Django将秒转换为xx天xx时xx分,具体代码如下所示: from django.utils.translation import ngettext_lazy as _n def humanize_seconds(secs): a_day = 86400 an_hour = 3600 a_minute = 60 timetot = '' total_secs = secs if secs > a_day: # 60sec * 60min * 24hrs days = int(secs //

  • django 将model转换为字典的方法示例

    平常的开发过程中不免遇到需要把model转成字典的需求,尤其是现在流行前后端分离架构,Json格式几乎成了前后端之间数据交换的标准,这种model转dict的需求就更多了,本文介绍日常使用的方法以供参考 from django.forms.models import model_to_dict from projects.models import ProjectInformation site = ProjectInformation.objects.get(id=6) dict = mode

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

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

  • Java中SimpleDateFormat日期格式转换详解及代码示例

    SimpleDateFormat是处理日期格式转换的类. 官方API_1.8关于SimpleDateFormat继承于DateFormate截图: SimpleDateFormat的构造器如下: SimpleDateFormat中的格式定义,常用的用红色框圈出: 中文解释: y : 年 M : 年中的月份 D : 年中的天数 d : 月中的天数 w : 年中的周数 W : 月中的周数 a : 上下/下午 H : 一天中的小时数(0-23) h : 一天中的小时数(0-12) m : 小时中的分钟

  • SQL SERVER 日期格式转换详解

    SQL SERVER 2000用sql语句如何获得当前系统时间就是用GETDATE(); Sql中的getDate()2008年01月08日 星期二 14:59Sql Server 中一个非常强大的日期格式化函数 复制代码 代码如下: Select CONVERT(varchar(100), GETDATE(), 0);-- 05 16 2008 10:57AMSelect CONVERT(varchar(100), GETDATE(), 1);-- 05/16/08Select CONVERT

  • 自定义时间格式转换代码分享

    复制代码 代码如下: /// <summary>        /// 将日期字符串转换为日期类型        /// </summary>        /// <param name="strDateTime">形如"2012年5月14日"的日期字符串</param>        private DateTime ParseDateTime(string strDateTime)        {       

  • Django中日期时间型字段进行年月日时分秒分组统计

    1.数据结构说明: 数据结构如下:modification字段为修改数据时间字段,格式为 年,月,日,时,分,秒. 案例场景为,根据modification字段,统计每个统计粒子,产生数据的条数.如需要统计2020年10月29日 每个小时段产生数据的条数. 要进行这种统计需要用到 Django的connection库. 统计年月日粒子用 date_trunc_sql,统计时分秒用 datetime_extract_sql 2.进行年月日粒子的统计  2.1 官方 date_trunc_sql 原

  • Django自定义用户认证示例详解

    前言 Django附带的认证对于大多数常见情况来说已经足够了,但是如何在 Django 中使用自定义的数据表进行用户认证,有一种较为笨蛋的办法就是自定义好数据表后,使用OnetoOne来跟 Django 的表进行关联,类似于这样: from django.contrib.auth.models import User class UserProfile(models.Model): """ 用户账号表 """ user = models.OneT

  • java 中自定义OutputFormat的实例详解

    java 中 自定义OutputFormat的实例详解 实例代码: package com.ccse.hadoop.outputformat; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apa

  • 在MySQL中自定义参数的使用详解

    MySQL变量包括系统变量和系统变量.这次的学习任务是用户自定义变量.用户变量主要包括局部变量和会话变量. 用户自定义变量的声明方法形如:@var_name,其中变量名称由字母.数字."."."_"和"$"组成.当然,在以字符串或者标识符引用时也可以包含其他字符(例如:@'my-var',@"my-var",或者@my-var). 用户自定义变量是会话级别的变量.其变量的作用域仅限于声明其的客户端链接.当这个客户端断开时,其所

  • 对django xadmin自定义菜单的实例详解

    1. 自定义菜单 adminx.py class GlobalSetting(object): site_title = u'xxx后台' def kuF_site_menu(self): return [{ 'title': u'用户&账户', 'perm': self.get_model_perm(User, 'view'), 'icon':'fa fa-users', 'menus':( {'title': u'用户', 'url': self.get_model_url(User, 'c

  • Android Studio 中aidl的自定义类的使用详解

    自己折腾了好久,记录一下. service端: 1:创建类Dog,需要实现Parcelable接口: 2:aidl下创建 Dog.aidl,里面两句话就可以了 (1)package s包名; (2)parcelable Dog; 3:interface.aidl引入Dog类, import s包名.Dog; Client 端: 1:创建类Dog,需要实现Parcelable接口: 2:aidl下创建 Dog.aidl, (1)package c包名; (2)parcelable Dog; 注意:

随机推荐