Code

Opened 6 years ago

Closed 6 years ago

#8586 closed (invalid)

ImageFieldFile cannot be saved with File.read()

Reported by: rokclimb15 Owned by: nobody
Component: File uploads/storage Version: master
Severity: Keywords:
Cc: martin@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Both of these forms of data are rejected by get_image_dimensions, but accepted by FieldFile.save(). If you use an object with attr read, like get_image_dimensions wants, it is rejected by the default file storage since it doesn't have a chunk method. This is very useful if you want to duplicate an image behind the scenes for manipulation.

This may be related to #8208, since it is making this call before the image data has been written to the filesystem. It may need to be called after the ancestor save to get the proper filename (and fix #8208).

Traceback:

File "/usr/lib/python2.5/site-packages/django/core/handlers/base.py" in get_response
  86.                 response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/sites.py" in root
  173.                 return self.model_page(request, *url.split('/', 2))
File "/usr/lib/python2.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  44.         response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/sites.py" in model_page
  192.         return admin_obj(request, rest_of_url)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/options.py" in __call__
  191.             return self.change_view(request, unquote(url))
File "/usr/lib/python2.5/site-packages/django/db/transaction.py" in _commit_on_success
  238.                 res = func(*args, **kw)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/options.py" in change_view
  570.                 self.save_model(request, new_object, form, change=True)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/options.py" in save_model
  367.         obj.save()
File "/media/MORTON USB/sites/btevents/../btevents/photos/models.py" in save
  19.             self.slideshow_image.save(os_path.basename(self.image.path), self.image.read(), save=False)
File "/usr/lib/python2.5/site-packages/django/db/models/fields/files.py" in save
  262.         self._dimensions_cache = get_image_dimensions(content)
File "/usr/lib/python2.5/site-packages/django/core/files/images.py" in get_image_dimensions
  34.         file = open(file_or_path, 'rb')

Exception Type: TypeError at /admin/photos/photo/9/
Exception Value: file() argument 1 must be (encoded string without NULL bytes), not str

Here is a snippet to reproduce the problem.

class Photo(models.Model):
    image = models.ImageField(upload_to='event_photos')
    slideshow_image = models.ImageField(upload_to='slideshow', editable=False)

    def save(self):
        # save a stub image to get the filename we want from the FileStorage object
        self.slideshow_image.save(os.path.basename(self.image.path), self.image.read(), save=False)
        i = Image.open(self.slideshow_image.path)
        image = i.crop((0, 0, 450, 300))
        image.save(self.slideshow_image.path, 'JPEG')
        super(Photo, self).save()

Attachments (0)

Change History (3)

comment:1 Changed 6 years ago by kylefox

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Should've you be passing the File object into slideshow_image.save(), rather than the result of read()?

I haven't tested this, but my understanding is that your statement should be:

    self.slideshow_image.save(os.path.basename(self.image.path), self.image, save=False)

comment:2 Changed 6 years ago by anonymous

  • Cc martin@… added

comment:3 Changed 6 years ago by SmileyChris

  • Resolution set to invalid
  • Status changed from new to closed

kylefox is correct - you should be passing the File object in rather than the result of read() (and see #8501 for extending file storage so it handles saving basic file-like objects too)

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.