1

I'm trying to attach in a model a file that is currently not on the disk, but exist in memory. The model use django-filer, if I pass a regular file it works, with io stream it fails.

def test_save_bytesio():
from PIL import Image
import io

from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.files.uploadedfile import SimpleUploadedFile

img = Image.new("RGB",(4,4))
thumb_io = io.BytesIO()
img.save(thumb_io, format='JPEG')

# thumb_file = InMemoryUploadedFile(thumb_io, None, '{}_da_ordine.jpg'.format(1), 'image/jpeg',
#    thumb_io,None)
thumb_file = DjangoFile(thumb_io.getvalue(), name='gigi')
#thumb_file = DjangoFile(thumb_io, name='gigi')

mymodel = MyModelTosave.objects.create(
                 name='gigi',
                 file=thumb_file
               )

this is the error stack:

    return field.pre_save(obj, add=True)
../../.local/share/virtualenvs/--M2Y9QA9/lib/python3.7/site-packages/django/db/models/fields/files.py:288: in pre_save
    file.save(file.name, file.file, save=False)
../../.local/share/virtualenvs/--M2Y9QA9/lib/python3.7/site-packages/filer/fields/multistorage_file.py:121: in save
    content.seek(0)  # Ensure we upload the whole file
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <File: gigi>

>   seek = property(lambda self: self.file.seek)
E   AttributeError: 'bytes' object has no attribute 'seek'

../../.local/share/virtualenvs/--M2Y9QA9/lib/python3.7/site-packages/django/core/files/utils.py:20: AttributeError

The problem seems to be this row:

                         name='gigi',
>                        file=thumb_file
                       )

What's the correct way to pass the thumb_file to file field?

user2239318
  • 2,578
  • 7
  • 28
  • 50

2 Answers2

1

Adding this before createing the Djangofile did the trick:

thumb_io.seek(0)
user2239318
  • 2,578
  • 7
  • 28
  • 50
0

Try creating an instance of the model first, and then call save() separately on the FileField, wrapping the BytesIO instance in Django's File, such as:

from django.core.files import File

mymodel = MyModelTosave()
mymodel.file.save('gigi', File(thumb_io), True)

Note that the third argument True ensures that the model instance itself is saved, after the file save has completed.

Will Keeling
  • 22,055
  • 4
  • 51
  • 61