簡體   English   中英

如何在Django ModelForm中調整圖像大小?

[英]How to resize image in django ModelForm?

我有以下ModelForm

class MyModelForm(ModelForm):

    def __init__(self, *a, **kw):
        super().__init__(*a, **kw)
        self.fields['image'].validators = []

    def clean_image(self):
        img = self.cleaned_data.get('image')
        if not img:
            return img
        # Resize to Max 1024x1024 px
        new_size = (1024, 1024)
        if any(x>new_size[0] for x in img.image.size):
            img.image.thumbnail(new_size)
        return img

當我嘗試上傳圖片時,它將引發錯誤:

異常類型:/ some / view處的AttributeError
異常值:'NoneType'對象沒有屬性'read'

完整回溯:

Traceback:

File "/usr/local/lib/python3.6/site-packages/PIL/ImageFile.py" in load
  147.             read = self.load_read

During handling of the above exception ('JpegImageFile' object has no attribute 'load_read'), another exception occurred:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/opt/django/portal/views/advert.py" in post
  167.         if not all([f.is_valid() for f in (usr_form, adv_form)]):

File "/opt/django/portal/views/advert.py" in <listcomp>
  167.         if not all([f.is_valid() for f in (usr_form, adv_form)]):

File "/usr/local/lib/python3.6/site-packages/django/forms/forms.py" in is_valid
  183.         return self.is_bound and not self.errors

File "/usr/local/lib/python3.6/site-packages/django/forms/forms.py" in errors
  175.             self.full_clean()

File "/usr/local/lib/python3.6/site-packages/django/forms/forms.py" in full_clean
  384.         self._clean_fields()

File "/usr/local/lib/python3.6/site-packages/django/forms/forms.py" in _clean_fields
  405.                     value = getattr(self, 'clean_%s' % name)()

File "/opt/django/portal/forms.py" in clean_image
  57.             img.image.thumbnail(new_size)

File "/usr/local/lib/python3.6/site-packages/PIL/Image.py" in thumbnail
  2008.         im = self.resize(size, resample)

File "/usr/local/lib/python3.6/site-packages/PIL/Image.py" in resize
  1697.         self.load()

File "/usr/local/lib/python3.6/site-packages/PIL/ImageFile.py" in load
  151.             read = self.fp.read

Exception Type: AttributeError at /some/view
Exception Value: 'NoneType' object has no attribute 'read'

我想這是因為怎樣ImageField實現django

image = Image.open(file)
# verify() must be called immediately after the constructor.
image.verify()

# Annotating so subclasses can reuse it for their own validation
f.image = image

根據某些消息來源,我應該在調用verify()之后重新打開圖像文件,但是我不確定該怎么做,或者這是否是解決問題的最佳方法?

默認情況下,Django ImageField驗證上傳的文件包含有效圖像,實際上它會將圖像數據移交給PIL進行處理。 可以將ImageField子類化並覆蓋其to_python方法,以便在驗證的第一步應用調整大小過濾器,但是實現自定義clean_*方法更方便,下面是一個示例:

class MyModel(models.Model):
    image = models.ImageField(upload_to='images/%Y/%m/%d/', blank=True, null=True)


class MyModelForm(ModelForm):

    def clean_image(self):
        img = self.cleaned_data.get('image')
        if not img:
            return img
        maxdim = 1024
        if any(dim > maxdim for dim in img.image.size):
            # Resize too large image up to the max_size
            from PIL import Image
            i = Image.open(img.file)
            fmt = i.format.lower()
            i.thumbnail((maxdim, maxdim))
            # We must reset io.BytesIO object, otherwise resized image bytes
            # will get appended to the original image  
            img.file = type(img.file)()
            i.save(img.file, fmt)
        return img

    class Meta:
        model = models.MyModel

注意事項:

  • 原始圖像bytes存儲在img.file屬性中
  • img.file是實例io.BytesIO
  • PIL.Image實例。 圖像存儲在img.image屬性中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM