我有以下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
的{{3}}是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()
根据一些implemented我应该在调用|
后重新打开图像文件,但我不知道我该怎么办?或者这是否是解决问题的最佳方法?< / p>
答案 0 :(得分:0)
Django ImageField
默认情况下会验证上传的文件是否包含有效图片,实际上它会将图像数据移交给PIL
进行处理。可以将ImageField
子类化并覆盖其to_python
方法,以便在验证的第一步应用resize过滤器,但是实现自定义clean_*
方法更方便,这是一个示例:< / p>
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
orig的实例。图像存储在img.image
属性