【问题标题】:a StringIO like class, that extends django.core.files.File一个类似 StringIO 的类,它扩展了 django.core.files.File
【发布时间】:2011-03-20 19:54:21
【问题描述】:
class MyModel(models.Model)
 image = models.FileField(upload_to="blagh blagh...")
 #more spam...

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

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

我尝试使用 StringIO,但它没有扩展 django.core.files.File,因此没有实现方法 chunks()。我已经将它包装在这样的 File 对象中:

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

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

【问题讨论】:

  • 使用Image 类。
  • 我考虑过,但后来我不会使用 django 机制来命名文件(如果存在给定名称的文件,请在文件名中添加下划线)。是的,我知道,我可以自己做到这一点,也可以通过其他方式做到这一点,但如果我这样做是最好的,就像我之前描述的那样。

标签: python django


【解决方案1】:

如果您有一个字节流,您想将其保存到 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 的第二个参数是模型中字段的名称,因此是“图像”

这有点麻烦,但它可以完成工作。希望 API 会在 1.3/4 中得到更多的清理。

编辑:
请参阅Jason's answer 了解更简单的方法,但您仍然想知道图像的文件名。

【讨论】:

    【解决方案2】:

    您可以使用 ContentFile 代替 File

    from django.core.files.base import ContentFile
    
    photo.image.save(name, ContentFile(buffer))
    

    【讨论】:

    • 整洁!这比我的解决方案简单得多...+1
    • 如果缓冲区是StringIO 对象,您需要执行ContentFile(buffer.getvalue())
    【解决方案3】:

    关于杰森的回答。请注意,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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多