Django在表单中调整图像大小

时间:2018-11-21 05:29:20

标签: django resize python-imaging-library

我正在使用python 3.6和Django 2.0。

我有一张要上传到模型的正方形图像。我目前在模型中有一个图片字段,可以上传。

avatar             = models.ImageField(path_and_rename, max_length=255, blank=True

我想将上传的任何正方形图像的大小调整为750到750。我想到了一种实现方法,但是我不认为我将其保存为正确的类型,因为它给我一个错误。

'Image' object has no attribute '_committed'

如何调整方形图像的尺寸以满足我需要的新尺寸。

我的代码(省去了验证使其更简单):

forms.py

def clean_avatar(self):
  avatar = self.cleaned_data['avatar']
  try:
    print(len(avatar))
    w, h = get_image_dimensions(avatar)
    max_width = max_height = 750
    image = Image.open(avatar)
    resized_image = image.resize((max_width,max_height), Image.ANTIALIAS)
    print(type(avatar))
    print(type(image))
    print(type(resized_image))
    return resized_image
  except
    ...

上面的输出是

<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
<class 'PIL.JpegImagePlugin.JpegImageFile'>
<class 'PIL.Image.Image'>

如果我返回avatar,它会起作用,但是当我返回resized_image时,它将不起作用。如何使resized_image的数据类型为avatar

完整错误消息:

File "C:\myapp\lib\site-packages\django\core\handlers\exception.py" in inner


35.             response = get_response(request)

File "C:\myapp\lib\site-packages\django\core\handlers\base.py" in _get_response
  128.                 response = self.process_exception_by_middleware(e, request)

File "C:\myapp\lib\site-packages\django\core\handlers\base.py" in _get_response
  126.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\myapp\lib\site-packages\django\views\generic\base.py" in view
  69.             return self.dispatch(request, *args, **kwargs)

File "C:\myapp\lib\site-packages\django\contrib\auth\mixins.py" in dispatch
  52.         return super().dispatch(request, *args, **kwargs)

File "C:\myapp\lib\site-packages\django\views\generic\base.py" in dispatch
  89.         return handler(request, *args, **kwargs)

File "C:\myapp\lib\site-packages\django\views\generic\edit.py" in post
  194.         return super().post(request, *args, **kwargs)

File "C:\myapp\lib\site-packages\django\views\generic\edit.py" in post
  142.             return self.form_valid(form)

File "C:\myapp\lib\site-packages\django\views\generic\edit.py" in form_valid
  125.         self.object = form.save()

File "C:\myapp\lib\site-packages\django\forms\models.py" in save
  456.             self.instance.save()

File "C:\myapp\lib\site-packages\django\contrib\auth\base_user.py" in save
  73.         super().save(*args, **kwargs)

File "C:\myapp\lib\site-packages\django\db\models\base.py" in save
  729.                        force_update=force_update, update_fields=update_fields)

File "C:\myapp\lib\site-packages\django\db\models\base.py" in save_base
  759.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "C:\myapp\lib\site-packages\django\db\models\base.py" in _save_table
  820.                       for f in non_pks]

File "C:\myapp\lib\site-packages\django\db\models\base.py" in <listcomp>
  820.                       for f in non_pks]

File "C:\myapp\lib\site-packages\django\db\models\fields\files.py" in pre_save
  285.         if file and not file._committed:

Exception Type: AttributeError at /account/details/
Exception Value: 'Image' object has no attribute '_committed'

1 个答案:

答案 0 :(得分:0)

我做了类似的事情,但是没有形式。我的方法是这样的:

# override Model Save Method

class YourModel(models.Model):
  ...
  def save(self, **kwargs):
     resize = kwargs.pop('resize', False)
     instance = super(YourModel, self).save(**kwargs)
     if resize:
        pil_image = Image.open(self.avatar.path)
        # resize related code
        resized_image = pil_image.resize((max_width,max_height), Image.ANTIALIAS)
        resized_image.save(self.avatar.path)

     return instance

并从如下形式调用此保存方法:

 class YourForm(...):
     ...
     def save(self, commit=True):
        instance = super(YourForm, self).save(commit=False)
        instance.save(resize=True)  # call model save method from here
        return instance

更新

也许您可以这样尝试:

import io 

# clean method
w, h = get_image_dimensions(avatar)
max_width = max_height = 750
image = Image.open(avatar)
resized_image = image.resize((max_width,max_height), Image.ANTIALIAS)
img_in_memory = io.BytesIO()
resized_image.save(img_in_memory, format="png")
return img_in_memory