Django - NullBooleanField won't retain False value from custom save() method
刚来Django的人,如果我错过了一些明显的事情或者做了一些愚蠢的事情,请原谅我…
我有一个带有自定义save()扩展名的django模型。修剪不相关的字段和方法,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Content(models.Model): url = models.URLField(max_length=1000) image = models.URLField(blank=True, max_length=1000) image_type = models.NullBooleanField(default=None) def save(self, *args, **kwargs): if self.url: img, img_type = image_extractor(self.url) print 'extractor returned: ', img_type print 'before set: ', self.image_type setattr(self, 'image', img) setattr(self, 'image_type', img_type) print 'after set: ', self.image_type super(Content, self).save(*args, **kwargs) print 'from query: ', Content.objects.get(url=self.url).image_type |
image提取器函数返回一个URL字符串和一个表示图像类型的布尔值:对于大于某个宽度的图像为true,对于较小的图像为false,如果找不到合适的图像,则为none。问题是,当我查询content.objects并检查image_type时,所有对象都返回true或none。因此打印语句。图像类型为"无"或"真"的图像按预期工作,但当图像类型返回"假"时,打印内容如下:
1 2 3 4 | extractor returned: False before set: None after set: False from query: True |
无论如何,对super().save的调用总是在我尝试设置false时将image_类型恢复为true(但如果我不设置,则不会)。我承认,我不太了解super(),但是根据文档,在扩展模型函数时似乎有必要这样做。有人能解释一下这里发生了什么事吗?我该怎么解决?
编辑:我注意到我可以通过管理页面将值更改为false,它保持为false。但我仍然需要修复save()方法。现在,我刚刚用一个整型字段替换了布尔字段,并将值保存为0或1,这确实有效。但我还是想知道为什么更合适的领域没有。
自从写下这个问题以来,我提出了一个临时的解决方案,即使用integerfield将布尔值存储为0或1。在决定今晚重新审视这个问题并回到Nullbooleanfield之后,突然一切都按预期工作了。所以看起来丹诺诺万是正确的:上面的代码是正确的,不幸的是,我仍然不知道是什么导致了这个错误。我在使用integerfield时更改的其他内容一定解决了这个问题。多亏你们中的一些人看了一眼,提出了一些意见,我很抱歉浪费了你们的时间。
重载保存方法的方式看起来不错。我认为您没有从数据库加载好的对象。使用主键可能会更好。
在您的情况下,只需替换:
1 | Content.objects.get(url=self.url).image_type |
通过:
1 | Content.objects.get(pk=self.pk).image_type |
查看文档:https://docs.djangoproject.com/en/dev/ref/models/instances/pk属性
摘自Django文件:
Once the object has been saved, you must reload the object in order to
access the actual value that was applied to the updated field:product = Products.objects.get(pk=product.pk)
print(product.number_sold)
< /块引用>< /块引用>< /块引用>