一个类似StringIO的类,它扩展了Django.core.files.Fi

2024-05-23 15:23:26 发布

您现在位置:Python中文网/ 问答频道 /正文

class MyModel(models.Model)
 image = models.FileField(upload_to="blagh blagh...")
 #more spam...

我在内存中有一个文件,我想通过Django FileField save方法保存它,如下所示:

photo.image.save(name, buffer) # second arg should be django File

我试过使用StringIO,但它没有扩展django.core.files.File,因此也没有实现方法chunks()。我把它包装在一个类似这样的文件对象中:

buffile = File(buffer, name) # first argument should be a file
photo.image.save(name, buffile)

但是文件方法使用所提供文件的大小和名称字段。StringIO没有定义它们。 我找到了this,但是链接已经死了


Tags: 文件django方法nameimagemodelssavebuffer
3条回答

您可以使用ContentFile而不是File

from django.core.files.base import ContentFile

photo.image.save(name, ContentFile(buffer))

是杰森的答案。请注意,ContentFile只接受字符串,而不接受任何类似文件的对象。这里有一个

from django.core.files.base import *

class StreamFile(ContentFile):
    """
    Django doesn't provide a File wrapper suitable 
    for file-like objects (eg StringIO)
    """
    def __init__(self, stream):
        super(ContentFile, self).__init__(stream)
        stream.seek(0, 2)
        self.size = stream.tell()

现在你可以做这样的事情——

photo.image.save(name, StreamFile(io))

如果您有一个字节流,希望将其保存到FileField/ImageField中,下面的一些代码可能会有所帮助:

>>> from django.core.files.uploadedfile import InMemoryUploadedFile
>>> from cStringIO import StringIO
>>> buf = StringIO(data)  # `data` is your stream of bytes
>>> buf.seek(0, 2)  # Seek to the end of the stream, so we can get its length with `buf.tell()`
>>> file = InMemoryUploadedFile(buf, "image", "some_filename.png", None, buf.tell(), None)
>>> photo.image.save(file.name, file)  # `photo` is an instance of `MyModel`
>>> photo.image
<ImageFieldFile: ...>

一些注释:

  • 你可以为图像编出你想要的任何名字,但是你可能想保持扩展名的准确性
  • InMemoryUploadedFile的第二个参数是模型中字段的名称,因此是“image”

这有点费尼基,但能完成任务。希望API在1.3/4中得到更多的清理。

编辑:
有关更简单的方法,请参见Jason's answer,不过您仍然需要知道图像的文件名。

相关问题 更多 >