编程中遇到一个难题,因为对模型中的外键比较运算理解不到位,陷入死循环的境地。模型如下:
class Business(models.Model):
name = models.CharField(max_length=30, blank=False, null=False, unique=True)
code = models.CharField(max_length=20, blank=True, null=True, unique=True)
在一处视图代码中有一个以Business为外键的比较运算
abx_s=AirlineBusiness.objects.filter(business=ab.business,airline=ab.airline)
最初开发时一切正常,没有提示什么错误。之后需要为Business增加一个amount字段,正在运行的服务器中断,提示没有Business.amount字段,由于还没有执行makemigrations和migrate,当然不会有这个字段。于是执行:
python manage.py makemigrations
结果无法顺利执行,仍然提示没有Business.amount字段,提示出错的代码就是:
abx_s=AirlineBusiness.objects.filter(business=ab.business,airline=ab.airline)
似乎makemigrations操作之前会检查涉及的model代码,于是就形成了死结:
增加字段==>需要执行makemigrations==>会进行检查代码,进行外键比较==>发现没有要新增的字段==>无法进行外键比较==>无法makemigrations==>无法新增字段
只好把涉及的比较运算的代码注释掉,然后执行makemigrations,再取消注释。问题虽然暂时解决,但相当的不优雅。
今天再次遇到类似情况,静心分析,终于找到问题所在,原来都是比较运算挖的坑。
“比较”是编程中最常见的操作,python中,等于操作又细分为 is和 ==,is用于比较对象的id是否相同,id相同则为True,否则为False。==操作比较的值是否相等,不考虑对象的id。
>>> x=5
>>> id(x)
9326880
>>> y=5
>>> id(y)
9326880
>>> x is y
True
>>> x=[1,2,3]
>>> y=[1,2,3]
>>> x==y
True
>>> x is y
False
回头看外键比较运算代码:
abx_s=AirlineBusiness.objects.filter(business=ab.business,airline=ab.airline)
这里的比较运算应该是==运算,那么就应该是对比值,所以系统要对比外键模型的每个字段是否相等,包括刚刚增加,还没有来得及migrate到数据库中的字段,于是发现数据库里面没有拟增加的字段,报错!
找到了问题的根源,接下来寻找解决办法。这里外键比较的本意其实是检查是否同一数据记录,即数据行的id是否相同,而django的模型对外键字段,其实是隐藏一个对应的id字段,比如开头那个例子,就隐藏着一个business_id字段(整数字段)。外键字段的比较,其实就是要比较id是否相等。因此解决方法如下:
abx_s=AirlineBusiness.objects.filter(business_id=ab.business_id,airline=ab.airline)
注意正解是:business_id==ab.business_id
而这个就不行:business_id==ab.business.id,包括赋值操作也不行,这一点难以理解。
有一点复杂,表述清楚没?
网友评论