【问题标题】:Django Image upload and resizeDjango图像上传和调整大小
【发布时间】:2011-10-24 15:27:45
【问题描述】:

我有一个带有图像字段的标准 Django 表单。上传图片时,我想确保图片不大于 300 像素 x 300 像素。这是我的代码:

def post(request):
    if request.method == 'POST':
        instance = Product(posted_by=request.user)
        form = ProductModelForm(request.POST or None, request.FILES or None)
        if form.is_valid():
           new_product = form.save(commit=False)
           if 'image' in request.FILES:
              img = Image.open(form.cleaned_data['image'])
              img.thumbnail((300, 300), Image.ANTIALIAS)

              # this doesnt save the contents here...
              img.save(new_product.image)

              # ..because this prints the original width (2830px in my case)
              print new_product.image.width

我面临的问题是,我不清楚如何将 Image 类型转换为 ImageField 类型。

【问题讨论】:

  • 如果我有这个错误,请原谅我,我暂时不会使用 Pil。在您执行form.save() 之后,它会根据您的设置将其放在您的媒体文件夹中。为什么你不能在那里改变它并重新保存它?您似乎从响应中获取了它的副本。

标签: python django python-imaging-library image-uploading


【解决方案1】:

来自 ImageField 的 save method 上的文档:

注意,内容参数应该是 django.core.files.File 的一个实例,而不是 Python 的内置文件对象。

这意味着您需要将 PIL.Image (img) 转换为 Python 文件对象,然后将 Python 对象转换为 django.core.files.File 对象。像这样的东西(我没有测试过这段代码)可能会起作用:

img.thumbnail((300, 300), Image.ANTIALIAS)

# Convert PIL.Image to a string, and then to a Django file
# object. We use ContentFile instead of File because the
# former can operate on strings.
from django.core.files.base import ContentFile
djangofile = ContentFile(img.tostring())
new_product.image.save(filename, djangofile)

【讨论】:

    【解决方案2】:

    您去吧,只需稍作更改以满足您的需要:

    class PhotoField(forms.FileField, object):
    
        def __init__(self, *args, **kwargs):
            super(PhotoField, self).__init__(*args, **kwargs)
            self.help_text = "Images over 500kb will be resized to keep under 500kb limit, which may result in some loss of quality"
    
        def validate(self,image):
            if not str(image).split('.')[-1].lower() in ["jpg","jpeg","png","gif"]:
                raise ValidationError("File format not supported, please try again and upload a JPG/PNG/GIF file")
    
        def to_python(self, image):
            try:
                limit = 500000
                num_of_tries = 10
                img = Image.open(image.file)
                width, height = img.size
                ratio = float(width) / float(height)
    
                upload_dir = settings.FILE_UPLOAD_TEMP_DIR if settings.FILE_UPLOAD_TEMP_DIR else '/tmp'
                tmp_file = open(os.path.join(upload_dir, str(uuid.uuid1())), "w")
                tmp_file.write(image.file.read())
                tmp_file.close()
    
                while os.path.getsize(tmp_file.name) > limit:
                    num_of_tries -= 1
                    width = 900 if num_of_tries == 0 else width - 100
                    height = int(width / ratio)
                    img.thumbnail((width, height), Image.ANTIALIAS)
                    img.save(tmp_file.name, img.format)
                    image.file = open(tmp_file.name)
                    if num_of_tries == 0:
                        break                    
            except:
                pass
            return image
    

    来源:http://james.lin.net.nz/2012/11/19/django-snippet-reduce-image-size-during-upload/

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 上面的链接坏了。
      【解决方案4】:

      这是一个可以解决这个问题的应用程序:django-smartfields

      from django.db import models
      
      from smartfields import fields
      from smartfields.dependencies import FileDependency
      from smartfields.processors import ImageProcessor
      
      class Product(models.Model):
          image = fields.ImageField(dependencies=[
              FileDependency(processor=ImageProcessor(
                  scale={'max_width': 300, 'max_height': 300}))
          ])
      

      【讨论】:

        【解决方案5】:

        在这里尝试我的解决方案:https://stackoverflow.com/a/25222000/3731039

        突出显示

        • 使用 Pillow 进行图像处理(需要两个包:libjpeg-dev、zlib1g-dev)
        • 使用 Model 和 ImageField 作为存储
        • 将 HTTP POST 或 PUT 与 multipart/form 一起使用
        • 无需手动将文件保存到磁盘。
        • 创建多个分辨率并存储它们的尺寸。

        【讨论】:

          【解决方案6】:

          你可以使用我的库django-sizedimagefield,它没有额外的依赖,使用非常简单。

          【讨论】:

            猜你喜欢
            • 2015-08-06
            • 2011-01-10
            • 2017-06-26
            • 2018-05-03
            • 2022-01-23
            • 2016-05-03
            • 1970-01-01
            • 2012-09-29
            • 2023-03-18
            相关资源
            最近更新 更多