在Django中,定义了一些Field来与数据库表中的字段进行映射,常用的字段类型。
类型说明AutoField一个自动增加的整数类型字段。通常你不需要自己编写它,Django会自动帮你添加字段:id=models.AutoField(primary_key=True),这是一个自增字段,从1开始计数。如果你非要自己设置主键,那么请务必将字段设置为primary_key=True。Django在一个模型中只允许有一个自增字段,并且该字段必须为主键!BigAutoField(1.10新增)64位整数类型自增字段,数字范围更大,从1到BigIntegerField64位整数字段(看清楚,非自增),类似IntegerField,-到。在Django的模板表单里体现为一个textinput标签。BooleanField布尔值类型。默认值是None。在HTML表单中体现为CheckboxInput标签。如果要接收null值,请使用NullBooleanField。CharField字符串类型。必须指定字符串最大长度max_length,如果超过了个字符,则不建议使用。默认的表单标签是inputtext。最常用的类型!CommaSeparatedIntegerField逗号分隔的整数类型。必须接收一个max_length参数。常用于表示较大的金额数目,例如1,,元。DateFieldclassDateField(auto_now=False,auto_now_add=False,**options)日期类型。一个Python中的datetime.date的实例。在HTML中表现为TextInput标签。在admin后台中,Django会帮你自动添加一个JS的日历表和一个“Today”快捷方式,以及附加的日期合法性验证。两个重要参数:(参数互斥,不能共存)auto_now:每当对象被保存时将字段设为当前日期,常用于保存最后修改时间。auto_now_add:每当对象被创建时,设为当前日期,常用于保存创建日期(注意,它是不可修改的)。设置上面两个参数就相当于给field添加了editable=False和blank=True属性。如果想具有修改属性,请用default参数。例子:pub_time=models.DateField(auto_now_add=True),自动添加发布时间。DateTimeField日期时间类型。Python的datetime.datetime的实例。与DateField相比就是多了小时、分和秒的显示,其它功能、参数、用法、默认值等等都一样。TimeField时间字段,Python中datetime.time的实例。接收同DateField一样的参数,只作用于小时、分和秒。DecimalField固定精度的十进制小数。相当于Python的Decimal实例,必须提供两个指定的参数!参数max_digits:最大的位数,必须大于或等于小数点位数。decimal_places:小数点位数,精度。当localize=False时,它在HTML表现为NumberInput标签,否则是text类型。例子:储存最大不超过,带有2位小数位精度的数,定义如下:models.DecimalField(...,max_digits=5,decimal_places=2)。DurationField持续时间类型。存储一定期间的时间长度。类似Python中的timedelta。在不同的数据库实现中有不同的表示方法。常用于进行时间之间的加减运算。但是小心了,这里有坑,PostgreSQL等数据库之间有兼容性问题!EmailField邮箱类型,默认max_length最大长度位。使用这个字段的好处是,可以使用DJango内置的EmailValidator进行邮箱地址合法性验证。FileFieldclassFileField(upload_to=None,max_length=,**options)上传文件类型,后面单独介绍。FilePathField文件路径类型,后面单独介绍FloatField浮点数类型,参考整数类型ImageField图像类型,后面单独介绍。IntegerField整数类型,最常用的字段之一。取值范围-到。在HTML中表现为NumberInput标签。GenericIPAddressFieldclassGenericIPAddressField(protocol=both,unpack_ipv4=False,**options)[source],IPV4或者IPV6地址,字符串形式,例如.0.2.30或者2a02:42fe::4在HTML中表现为TextInput标签。参数protocol默认值为‘both’,可选‘IPv4’或者‘IPv6’,表示你的IP地址类型。NullBooleanField类似布尔字段,只不过额外允许NULL作为选项之一。PositiveIntegerField正整数字段,包含0,最大。PositiveSmallIntegerField较小的正整数字段,从0到。SlugFieldslug是一个新闻行业的术语。一个slug就是一个某种东西的简短标签,包含字母、数字、下划线或者连接线,通常用于URLs中。可以设置max_length参数,默认为50。SmallIntegerField小整数,包含-到。TextField大量文本内容,在HTML中表现为Textarea标签,最常用的字段类型之一!如果你为它设置一个max_length参数,那么在前端页面中会受到输入字符数量限制,然而在模型和数据库层面却不受影响。只有CharField才能同时作用于两者。URLField一个用于保存URL地址的字符串类型,默认最大长度。UUIDField用于保存通用唯一识别码(UniversallyUniqueIdentifier)的字段。使用Python的UUID类。在PostgreSQL数据库中保存为uuid类型,其它数据库中为char(32)。这个字段是自增主键的最佳替代品,后面有例子展示。关于Django时间与时区设置问题:
**naivetime:**就是不带时区的时间。
**Activetime:**就是带时区的时间。
使用datetime.datetime.utcnow()、datetime.datetime.now()输出的类似以下就是不带时区的时间(naivetime)
importdatetime#说明:测试时间本地:-06-:09:18datetime.datetime.utcnow()#datetime.datetime(,6,20,14,8,46,)datetime.datetime.now()#datetime.datetime(,6,20,22,9,18,)
而使用django.utils.timezone.now()输出的类似以下的时间就是带时区的时间(Activetime),其中+00:00表示的就是时区相对性。
fromdjango.utilsimporttimezonetimezone.now()#datetime.datetime(,6,20,14,10,27,,tzinfo=UTC)
另外一个UTC时间,UTC时间表示的是格林尼治平均时即可,即零区时间。而北京时间表示的是东八区时间,即UTC+8。
上面是USE_TZ=True时,设置为False
importdatetimedatetime.datetime.utcnow()#datetime.datetime(,6,20,14,22,5,)datetime.datetime.now()#datetime.datetime(,6,20,22,22,31,)fromdjango.utilsimporttimezonetimezone.now()#datetime.datetime(,6,20,22,23,0,)
可以看出
datetime.datetime.now():输出的永远是本地时间(naivetime)与配置无任任何关系。
datetime.datetime.utcnow():输出的是UTC时间(naivetime),比本地时间小8个小时。
django.util.timezone.now():如果USE_TZ=True则输出的是UTC时间(activetime),如果配置USE_TZ=False,则与datetime.datetime.now()完全相同。
在Django的配置文件settings.py中,有两个配置参数是跟时间与时区有关的,分别是TIME_ZONE和USE_TZ。
TIME_ZONE=Asia/Shanghai#用于存放本地时区信息,默认值为UTC,意思为采用国际标准时间“格林尼治时间”。中国处于东八区,官方文档上有两个取值“Asia/Shanghai”和“Asia/Chongqing”(没有北京).#如果设置为True,Django会使用系统默认设置的时区,即America/Chicago,此时的TIME_ZONE不管有没有设置都不起作用。#如果为False,而TIME_ZONE设置为None,则Django还是会使用默认的America/Chicago时间。#若TIME_ZONE设置为其它时区的话,则还要分情况,如果是Windows系统,则TIME_ZONE设置是没用的,Django会使用本机的时间。如果为其他系统,则使用该时区的时间。USE_TZ=True#修改时区确认,默认是Ture,时间是utc时间,由于我们要用本地时间,所用手动修改为false#如果修改设置为USE_TZ=True与TIME_ZONE=Asia/Shanghai,用datetime.datetime.now()获取的时间由于不带时区,django会把这个时间当成Asia/Shanghai时间,即东八区时间,然后django会把这个时间转成带时区UTC时间存储到数据库中去,而读的时候直接按UTC时间读出来,这就是网上很多人遇到的存储到数据库中的时间比本地时间会小8个小时的原因。#如果设置了USE_TZ=True之后,model里面认为DateTimeField使用UTC时间(带时区的时间),#这时用datetime.datetime.now()获取的时间是不带时区的就会报这个问题。
我们根据USE_TZ的值看看效果:
classArticle(models.Model):....#TIME_ZONE=Asia/Shanghai,USE_TZ=False时迁移创建的create_time=models.DateTimeField(verbose_name=创建时间,auto_now_add=True)#TIME_ZONE=Asia/Shanghai,USE_TZ=True时迁移的update_time=models.DateTimeField(verbose_name=更新时间,auto_now=True)
问题:Django存储到数据库的时间比本地时间小8个小时??
Django在1.4版本以后存储设置USE_TZ=True,则存储到数据库中的时间永远是UTC时间;
如果Django设置USE_TZ=True与TIME_ZONE=UTC,用datetime.datetime.now()获取的时间django会把这个时间当成UTC时间存储到数据库中;
如果设置为USE_TZ=True与TIME_ZONE=Asia/Shanghai,用datetime.datetime.now()获取的时间由于不带时区,django会把这个时间当成Asia/Shanghai时间,即东八区时间,然后django会把这个时间转成带时区UTC时间存储到数据库中去(也就是比如用datetime.datetime.now()获取时间为16点,然后django会将其转UTC时间-8=8点存储到数据库中),而读的时候直接按UTC时间读出来,这就是存储到数据库中的时间比本地时间会小8个小时的原因。
如果设置了USE_TZ=True之后,model里面认为DateTimeField使用UTC时间(带时区的时间),这时用datetime.datetime.now()获取的时间是不带时区的就会报:DateTimeFieldrole_cost_history.cost_timereceivedanaivedatetime(-05-:59:01.)whiletimezonesupportisactive?。
控制台中直接获取数据:
fromarticle.modelsimportCategory,Article,Tagarticle=Article.objects.first()article.create_time#datetime.datetime(,7,4,10,35,4,)article.update_time#datetime.datetime(,7,4,2,25,53,)
页面上显示看看效果:
defindex(request):article=Article.objects.first()create_time=article.create_timeupdate_time=article.update_timeprint(create_time)#-07-:35:04.print(update_time)#-07-:25:53.#returnHttpResponse(create_time)#-07-:35:04.#returnHttpResponse(update_time)#-07-:25:53.returnrender(request,index.html,{create_time:create_time,update_time:update_time})
模板显示时间或读取时间:
如果设置了USE_TZ=True之后,如果设置TIME_ZONE=Asia/Shanghai,尽管数据库中存储的是UTC时间,但在模板显示的时候,会转成TIME_ZONE所示的本地时间进行显示。
总结:在django开发时,尽量使用UTC时间,即设置USE_TZ=True,TIME_ZONE=Asia/Shanghai,并且在获取时间的时候使用django.utils.timezone.now()。因为后台程序使用时间时UTC时间就能满足,也能保证证模板时间的正确显示。
二、模型字段常用参数imgnull与blank:**blank:**针对表单的,如果blank=True,表示表单填写该字段的时候可以不填,默认不允许为空。只是在form表单验证时可以为空,而在数据库上存储的是一个空字符串。
**null:**是针对数据库级别的,如果null=True,表示数据库的该字段可以为空,默认false不允许为空。日期型、时间型和数字型字段不接受空字符串,所以设置IntegerField,DateTimeField型字段可以为空时,需要将blank,null均设为True。
auto_now与auto_now_add区别:
auto_now_add:只有第一次才会生效,比如可以用于文章创建时间。
auto_now:每一次修改保存对象时都会将当前时间更新进去,只有调用Model.save()时更新,在以其他方式(例如QuerySet.update())更新其他字段时,不会更新该字段,但您可以在此类更新中为字段指定自定义值。可用于文章修改时间。
三、模型元选项每个model都可以定义一个Meta类,使用内部的classMeta定义模型的元数据,这个类中可以定义一些关于你的配置,Meta是一个model内部的类。
模型元数据是任何不是字段的数据,比如排序选项(ordering),数据库表名(db_table)或者人类可读的单复数名称(verbose_name和verbose_name_plural)。在模型中添加classMeta是完全可选的,所有选项都不是必须的。
classArticle(models.Model):id=models.AutoField(primary_key=True)title=models.CharField(verbose_name=标题,max_length=20,null=False)content=models.CharField(verbose_name=内容,max_length=,null=False)