说说Django数据库的null和blank
Django model的每个字段都会涉及到null和blank选项,但对于不同的字段,null和blank设置也不同。
blank:Django中的blank是针对表单来说的,即表单中的该字段,你可以啥都不填。这点挺好理解的。
null:默认为FALSE,把django的orm翻译成原声的,就是 create ******* not null,看到这你应该明白,null和blank针对的维度不同,null是针对数据库的。 如果null设置为True,Django 将会把数据库中空值保存为NULL 。
那么,现在问题就来了,假如我设置了blank为True,即表单中的字段为空值,那么null值到底该怎么设置呢,是跟着设置成True,还是为FALSE呢?
其实null的设置不能一概而论,而是要根据字段的类型来确定。字段类型就分成两大类:男人和女人。哈哈,开玩笑。主要是分成可以接受空字符串和不能接受空字符串两种类型。能接受空字符串类型意味着,不管你blank设成啥,就算传来了空字符串,我这照存不误;但如果不能接受空字符串,那么当你blank设置成True时,如果传来了一个空字符串,但我这个字段类型不能存储空字符串或者说是字符串啊。那此时我必须得把null设置成True,即当你blank为True,传来了空字符串,我就把该字段值存储为null。
哪些字符串能接受,哪些不能接受空字符串呢?
CharField,TextField等普通字符串类型当然你可以接受啦,DateField,DateTimeField,IntergerField等就不能,具体可以见下面的表格:
Field 类型 | 设置null=True | 设置blank=True |
---|---|---|
CharField, TextField, SlugField, EmailField, CommaSeparatedIntegerField等 |
不要设置 django规定储存空字符串来代表空值, 当从数据库中读取NULL或空值时都为空字符串 |
可以设置 设置后允许接受widget中为空值(即不填写), 储存到数据库时空值变为空字符串 |
FileField, ImageField |
不要设置 django实际储存的是路径的字符串, 因此同上 |
可以设置 同上 |
BooleanField | 不要设置 因为有NullBooleanField代替 |
不要设置 |
IntegerField, FloatField, DecimalField等 |
可以设置 如果你希望在数据库中能储存NULL |
可以设置 设置后允许接受widget中为空值(即不填写), 设置为True时必须同时设置null=True |
DateTimeField, DateField, TimeField等 |
可以设置 如果你希望在数据库中能储存NULL |
可以设置 设置后允许接受widget中为空值(即不填写), 设置为True时必须同时设置null=True |
ForeignKey, ManyToManyField, OneToOneField |
可以设置 如果你希望在数据库中能储存NULL |
可以设置 设置后允许接受widget中为空值(即不填写) |
GenericIPAddressField | 可以设置 如果你希望在数据库中能储存NULL |
可以设置 设置后允许接受widget中为空值(即不填写) |
IPAddressField | 不推荐设置 用GenericIPAddressField代替 |
不推荐设置 用GenericIPAddressField代替 |
上面的表格摘自网上,我们看一下数据的第一行,CharField等字符串说了不要设置,意思是你blank设不设置成True,null都不要设置成True。其实这隐士地牵扯到一个数据库内部的问题。就拿MySQL来说,MySQL建议最好不要设置null,因为null本身有自身的缺陷: NULL值是未知的,且占用空间,不走索引,DBA建议建表的时候最好设置字段是NOT NULL 来避免这种低效率的事情的发生。 然而 空值('')是不占用空间的 。此外当我们进行查询时,比如统计数目count, 进行count()统计某列的记录数的时候,如果采用的NULL值,系统自动忽略掉,但是空值是会进行统计到其中的。 因此,能不设null,就尽量不要设。
不过对于上面表格中说的要不要设置,我觉得说得有些欠妥,或者说是不严谨。比如当blank为True,没说到底应不应该设置成null。不过你只要记住,有些字符串是不能接受空字符串的,因此当你设置blank为True时,要记得将null也设为True,除非,你设置了默认值。
我下面的代码是个例子:
class UserProfile(models.Model):
avator = models.ImageField(upload_to='userimg',blank=True)
age = models.IntegerField(null=True,blank=True)
school = models.CharField(max_length=48,blank=True)
gender = models.CharField(default='男孩',max_length=10,choices=GENDER.items())
hobby = models.CharField(max_length=255,blank=True)
user = models.OneToOneField(User,unique=True)
motto = models.CharField(max_length=255,blank=True)
self_introduction = models.TextField(blank=True)
#phone = models.Ch arField(max_length=13,blank=True)
birthday = models.DateField(blank=True,default='2000-01-01')
avator是一个ImageField,但实际上还是以CharField字段进行存储的,因此可以不设null,age是整数,因此必须要同时设;再看最后,birthday是DateField,我没设null,是因为我设置了default值,如果是空,就自动填这个值了。
微信分享/微信扫码阅读