再Django中,你可以把字符串形式的数值赋值给IntegerField
,然后Django会默认把字符串转换成int。但是BooleanField
则不行,BooleanField
只能接受True和False,或者0和1(BTW:在python中True即是1,False即是0)。这对于很多网络参数上传的场景很不利,因为很多时候我们处于方便会将布尔型参数转换成字符串形式来上传。一个典型的场景是在使用Swfit的Alamofire框架中的upload
来上传Multipartform时,由于form参数只能添加Data
形式的参数,直接将Bool型转化成Data
会非常麻烦,带来编码类型的问题。例如采用如下的方式进行转化:
let dataToUpload = Data(bytes: boolVal, count: MemoryLayout<Bool>.size)
以这种形式上传最后被django接收到时,这个字段的值会是"\x00"
(False)或者"\x01"
(True),导致编码类型的错误。所以一个较为方便的方法是将bool型变量转化成字符串再上传。
let toText = boolVal ? "1" : "0"
form.append(toText.data(using: String.Encoding.utf8, allowLossyConversion: false)!, withName: key)
不过,这样虽然避免了编码问题,但是在后台赋值时直接将这个字段赋给相应的BooleanField的话,会永远是True(这是当然的,将字符串直接用bool()
做强制类型转换就会始终是True)。一个妥协的办法是现将得到的上传的字符型字段转换成Int,再赋值给BooleanField。不过,这里要给大家介绍一种更加整洁,更加一劳永逸的办法,就是我们来重定义BooleanField的行为,在为其复制时,自动将字符串以我们想要的规则转换成Bool值。代码如下:
from django.db.models import BooleanField as _BooleanField
class BooleanField(_BooleanField):
def get_prep_value(self, value):
if value in ("0", "false", "False"):
return False
elif value in ("1", "true", "True"):
return True
else:
return super(BooleanField, self).get_prep_value(value)
其中get_prep_value
这个函数会在Django准备把字段的值写入数据库时调用。