代码之家  ›  专栏  ›  技术社区  ›  coler-j

如何在内存中创建一个文件(不是上传的文件)并通过django默认存储保存到filefield?

  •  2
  • coler-j  · 技术社区  · 7 年前

    如果我要在内存中创建一个类似csv的文件对象,如下所示:

    output_stream = io.StringIO()
    sheet = pyexcel.get_sheet(records=data)
    sheet.save_to_memory(file_type='csv', stream=output_stream)
    

    如何将输出流中类似文件的对象保存到Django默认存储后端的文件中?

    class Example(models.Model):
        model_file = models.FileField(upload_to='', max_length=255, blank=True, null=True)
    

    我试过这样的方法:

    self.model_file.save(filename, ContentFile(output_stream.read()))
    

    但我得到了以下错误:

    "TypeError: ('data must be bytes, received', <class 'str'>)"
    

    PyExcel仅支持CSV类型文件的IO.StringIO流。

    回溯:

    ...
      File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\files\storage.py", line 49, in save
        return self._save(name, content)
      File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\storages\backends\gcloud.py", line 167, in _save
        content_type=file.mime_type)
      File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 1034, in upload_from_file
        size, num_retries, predefined_acl)
      File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 947, in _do_upload
        size, num_retries, predefined_acl)
      File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 759, in _do_multipart_upload
        transport, data, object_metadata, content_type)
      File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\resumable_media\requests\upload.py", line 94, in transmit
        data, metadata, content_type)
      File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\resumable_media\_upload.py", line 270, in _prepare_request
        raise TypeError(u'`data` must be bytes, received', type(data))
    TypeError: ('`data` must be bytes, received', <class 'str'>)
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Håken Lid    7 年前

    你可以从 StringIO 然后像这样转换成utf8编码的字节。

    self.model_file.save(filename, ContentFile(output_stream.getvalue().encode()))
    

    getvalue() 类似于 read() ,但无论当前流位置如何,都将始终获得StringIO的完整内容与 读取() 你可能需要使用 seek(0) 是的。