Django image resizing and convert before upload

后端 未结 8 1193
余生分开走
余生分开走 2020-12-07 19:15

I searched a lot on this subject but couldn\'t really find what I need. I\'ll explain my problem :

On my website, the user can upload an image. I need to resize this

相关标签:
8条回答
  • 2020-12-07 19:51

    The easiest solution:

    def compress(image):
        im = Image.open(image)
        # create a BytesIO object
        im_io = BytesIO() 
        # save image to BytesIO object
        im.save(im_io, 'JPEG', quality=70) 
        # create a django-friendly Files object
        new_image = File(im_io, name=image.name)
        return new_image
    
    0 讨论(0)
  • 2020-12-07 19:52

    Just put together this for my own project, took me a while before i realized that the bytes and the image is separate attributes on the Django ImageField, this solution worked for me with Python 3.6.

        def clean_image(self):
            image_field = self.cleaned_data.get('image')
            if image_field:
                try:
                    image_file = BytesIO(image_field.file.read())
                    image = Image.open(image_file)
                    image.thumbnail((300, 300), Image.ANTIALIAS)
                    image_file = BytesIO()
                    image.save(image_file, 'PNG')
                    image_field.file = image_file
                    image_field.image = image
    
                    return image_field
                except IOError:
                    logger.exception("Error during resize image")
    
    0 讨论(0)
  • 2020-12-07 20:01

    Here is one more package that works for me with minimal code modification - django-resized.

    models.py

    from django_resized import ResizedImageField
    
    class Post(models.Model):
        image = ResizedImageField(upload_to='uploads/%Y/%m/%d')
    

    settings.py

    DJANGORESIZED_DEFAULT_SIZE = [1024, 768]
    DJANGORESIZED_DEFAULT_QUALITY = 75
    DJANGORESIZED_DEFAULT_KEEP_META = True
    DJANGORESIZED_DEFAULT_FORCE_FORMAT = 'JPEG'
    DJANGORESIZED_DEFAULT_FORMAT_EXTENSIONS = {'JPEG': ".jpg"}
    DJANGORESIZED_DEFAULT_NORMALIZE_ROTATION = True
    

    That's it!

    0 讨论(0)
  • 2020-12-07 20:02

    This Worked for me try it. I am using Django 2.0.6 and Python 3.6.4

    from django.db import models
    from PIL import Image
    from io import BytesIO
    from django.core.files.uploadedfile import InMemoryUploadedFile
    
    class ImageUpload(models.Model):
        name = models.CharField(max_length=100)
        uploadedImage = models.ImageField(upload_to='Uploads/%Y/%m/', db_column="Upload an Image")
        def save(self, *args, **kwargs):
            imageTemproary = Image.open(self.uploadedImage)
            outputIoStream = BytesIO()
            imageTemproaryResized = imageTemproary.resize( (1020,573) ) 
            imageTemproaryResized.save(outputIoStream , format='JPEG', quality=85)
            outputIoStream.seek(0)
            self.uploadedImage = InMemoryUploadedFile(outputIoStream,'ImageField', "%s.jpg" %self.uploadedImage.name.split('.')[0], 'image/jpeg', sys.getsizeof(outputIoStream), None)
            super(ImageUpload, self).save(*args, **kwargs)
    
    0 讨论(0)
  • 2020-12-07 20:10
    from django.db import models
    from django.contrib.auth.models import User
    from PIL import Image
    
    
    
    class profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        bio = models.CharField(max_length=300)
        location = models.CharField(max_length=99)
        image = models.ImageField(default='default.jpg', upload_to='profile_pics')
    
        def save(self):
            super().save()  # saving image first
    
            img = Image.open(self.image.path) # Open image using self
    
            if img.height > 300 or img.width > 300:
                new_img = (300, 300)
                img.thumbnail(new_img)
                img.save(self.image.path)  # saving image at the same path
    

    This example shows how to upload image after image re-sizing. Change the pixel of new_img, whatever you want.

    0 讨论(0)
  • 2020-12-07 20:12

    First, it's best to establish the correct language. Django and Python exist only on the server side. Therefore, anything they manipulate, save, or otherwise use, has to be first sent to the server. If Django or Python is to manage the photo, the user MUST upload this photo to the server first. Once the photo is uploaded, Django is free to make changes before storing the file.

    If your concern is with upload bandwidth, and you don't want large files being uploaded, you will have to resize and reformat the photo on the client side. If this is a web application, this can be done using Javascript, but can not be done with Python, since Python does not operate on the client side for an application like yours.

    If your concern is not with bandwidth, then you're free to have the user "upload" the file, but then have Django resize and reformat it before saving.

    You are correct that you will want to override your save function for the photo object. I would recommend using a library to handle the resizing and reformatting, such as sorl.

    from sorl.thumbnail import ImageField, get_thumbnail
    
    class MyPhoto(models.Model):
        image = ImageField()
    
        def save(self, *args, **kwargs):
            if self.image:
                self.image = get_thumbnail(self.image, '500x600', quality=99, format='JPEG')
            super(MyPhoto, self).save(*args, **kwargs)
    

    Sorl is just a library I am confident and familiar with, but it takes some tuning and configuration. You can check out Pillow or something instead, and just replace the line overriding self.image.

    I also found a similar question here.

    Edit: saw the update to your comment response above. Also note that if your webserver is handling Django, and your files are being saved to some CDN, this method will work. The image will be resized on the webserver before being uploaded to your CDN (assuming your configuration is as I'm assuming).

    Hope this helps!

    0 讨论(0)
提交回复
热议问题