[英]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.