将BytesIO保存到Django ImageField

7

我有一个网络爬虫,想要下载它正在抓取的页面的图像,并将其保存为Django模型中的“截图” ImageField。我正在使用以下代码:

def save_screenshot(source,screenshot):
    box = (0, 0, 1200, 600)
    im = Image.open(io.BytesIO(screenshot))
    region = im.crop(box)
    tempfile_io = io.BytesIO()
    region.save(tempfile_io, 'JPEG', optimize=True, quality=70)
    source.screenshot.save(source.slug_name+"-screenshot",ContentFile(tempfile_io.getvalue()),save=True)

它将截图保存到/media/news_source_screenshots/目录,但不会将其保存到模型中。该模型字段定义如下:

screenshot = models.ImageField(upload_to='news_source_screenshots',blank=True,null=True)

我漏掉了什么?

我看到你正在保存没有数据的临时文件,你必须保存 region... 在 source.screenshot.save(source.slug_name+"-screenshot", ContentFile(region.get_value()), save=True) 中,记住现在 region 是你的临时文件,因为 tempfile_io 是一个空缓冲区。 - German Alzate
谢谢@german-alzate-martinez,但是当我尝试使用你的修复方法时,我得到了以下错误:code TypeError: 'Image' does not support the buffer interface code,此外图片也没有被保存在/media/news_source_screenshost/ 目录中。 - Anthony Ainsworth
尝试将缓冲区更改为字符串IO,返回什么区域? - German Alzate
我将代码中的 tempfile_io = io.BytesIO() 改为了 tempfile_io = io.StringIO(),但在 region.save 这行代码处出现了 TypeError: string argument expected, got 'bytes' 的错误提示。@german-alzate-martinez - Anthony Ainsworth
你的原始代码返回什么区域? - German Alzate
1个回答

3
所以事实证明上面的代码非常有效!问题在于我使用了以下代码来调用上述方法:
source = NewsSource.objects.get(name=name)
html,screenshot = get_url(source.url)
save_screenshot(source,screenshot)
source.save()

所以,save_screenshot方法起作用了,但是它所做的工作被我的source.save()调用覆盖了。真是奇怪!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接