程序化保存图像到Django ImageField导致无尽图像循环

2 投票
2 回答
982 浏览
提问于 2025-04-15 16:01

我有一个模型里面有个叫 save 的方法,代码大概是这样的:

def save(self, force_insert=False, force_update=False):
    img_url = "http://example.com/%s.jpg" % (self.title)
    name = urlparse(img_url).path.split('/')[-1]
    content = urllib.urlretrieve(img_url)
    self.image.save(name, File(open(content[0])), save=True)
    super(Test, self).save(force_insert, force_update)    

但是不知道为什么,这个方法导致了无限循环的图片创建,文件名里出现了越来越多的 _。最后我发现是因为Django报了个错,提示说它试图保存的文件字符太多了(我发现保存了242张图片)。

我当时是想用 这个问题里的信息。

有人知道这是怎么回事吗?

2 个回答

0

我不是百分之百确定,但可能是当你调用 self.image.save 时,它默认也会调用模型的保存方法,这样就可能导致无限循环。我没有测试过,但我觉得有这个可能。

如果真的是这个问题,我的建议是:在模型的保存方法里发送一个信号,这个信号包含当前实例的信息,然后再用一个单独的函数来下载、解析图片并保存它。

6

我从源代码中看到,调用 ImageFileField.save()(实际上是 FileField.save(),因为它是继承来的)会导致存储文件名的实例(也就是数据库中的一行数据)被更新。

这意味着在你的 save 方法中调用 ImageFileField.save(),而这个调用又会触发你自己的保存方法,从而导致了递归调用。

根据源代码,如果你想避免这种情况,只需在 self.image.save 中传递 save=False。这样做会把文件数据保存到磁盘,但不会保存实例(数据库中的一行数据)。不过在下一行你通过调用父类的方法来保存,所以我认为这时数据会被保存到数据库中。

实际上,save=False 这个参数的设计就是为了处理这种情况的!

撰写回答