4👍
The issue is that new versions of Django default to using MemoryFileUploadHandler
, which doesn’t create a temporary file, and therefore there is no file “name.” See related Django ticket.
You’ll probably have to modify your code a bit to make this work, but you can at least start getting the name property by setting:
FILE_UPLOAD_HANDLERS = [
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]
In your settings.py file.
You may find the code I’ve used to solve almost the exact same issue as helpful.
def clean_logo_file(self):
logo_file_field = self.cleaned_data.get('logo_file')
if logo_file_field:
try:
logo_file = logo_file_field.file
with Image.open(logo_file_field.file.name) as image:
image.thumbnail((512, 512), Image.ANTIALIAS)
image.save(logo_file, format=image.format)
logo_file_field.file = logo_file
return logo_file_field
except IOError:
logger.exception("Error during image resize.")
Additional information on upload handlers.
0👍
-
If file is bigger than 2.5mb (2621440 bytes) – Django will
useTemporaryFileUploadHandler
. -
Otherwise Django will use
MemoryFileUploadHandler
.
You can change FILE_UPLOAD_MAX_MEMORY_SIZE
(doc) in settings.py
Or change FILE_UPLOAD_HANDLERS
(doc) as Nostalg.io mentioned above.
My example with Django Rest Framework serializers
:
Broken code:
# models.py
class ImageModel(Model):
image = models.ImageField(upload_to='images/', null=False, blank=False)
# serializers.py
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = ImageModel
fields = ["id", "image"]
read_only_fields = ["id"]
def validate_image(self, user_img):
img = Image.open(user_img)
... # process image here
img_io = io.BytesIO()
img.save(img_io, format='JPEG', quality=100)
filename = "%s.jpg" % user_img.name.split('.')[0]
user_img.name = "%s.jpg" % user_img.name.split('.')[0]
user_img.file = img_io # BAD IDEA!!!
# This overrides django's tempfile._TemporaryFileWrapper() with _io.BytesIO() !!!
...
return user_img # if picture bigger than 2.5mb -> gives an error!
Fixed code:
#settings.py
FILE_UPLOAD_HANDLERS = [
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]
# serializers.py
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = ImageModel
fields = ["id", "image"]
read_only_fields = ["id"]
def validate_image(self, user_img):
img = Image.open(user_img)
... # process image here
# override old TemporaryFile image with edited image
path_to_tmp = user_img.file.name
new_filename = "%s.jpeg" % user_img.name.split('.')[0]
# set new image name
img.save(path_to_tmp, format='JPEG', quality=100)
user_img.name = new_filename
...
return user_img # no errors more :)
It might be more rational to process image by rewriting save()
method in models.py
, but I convert images in serializers.py
because of handly ValidationError()
🙂
- [Django]-Django admin upload and image to s3 and then resize the image and save a thumb problem
- [Django]-Saving many Django objects with one big INSERT statement
- [Django]-Using a Django FileField in an inline formset
- [Django]-Who should format my data for display?
- [Django]-DjangoCMS, use snippets outside of CMS templates