美文网首页
Django 外键比较运算遇到的坑

Django 外键比较运算遇到的坑

作者: 邹小伟 | 来源:发表于2020-02-07 19:23 被阅读0次

    编程中遇到一个难题,因为对模型中的外键比较运算理解不到位,陷入死循环的境地。模型如下:

    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,包括赋值操作也不行,这一点难以理解。

    有一点复杂,表述清楚没?

    相关文章

      网友评论

          本文标题:Django 外键比较运算遇到的坑

          本文链接:https://www.haomeiwen.com/subject/repmxhtx.html