说说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值,如果是空,就自动填这个值了。

 

 

--------EOF---------
微信分享/微信扫码阅读