使用PIL时,“ JpegImageFile”对象没有属性“ _committed”错误
问题内容:
我正在使用PIL压缩上传的图片(FileField
)。但是我遇到一个错误,我认为这是双重保存的问题?(保存我的图像,然后保存包括该图像的整个表单)。我想commit=False
在保存图像时执行,但似乎无法执行。这是我的代码:
...
if form_post.is_valid():
instance = form_post.save(commit=False)
instance.user = request.user
if instance.image:
filename = instance.image
instance.image = Image.open(instance.image)
instance.image.thumbnail((220, 130), Image.ANTIALIAS)
instance.image.save(filename, quality=60)
instance.save()
'JpegImageFile' object has no attribute '_committed'
在最后一行(instance.save()
)返回错误
有人可以找出问题所在吗?-知道我该如何解决吗?
完整回溯:
File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
23. return view_func(request, *args, **kwargs)
File "/Users/zorgan/Desktop/project/site/post/views.py" in post
68. if uploaded_file_type(instance) is True:
File "/Users/zorgan/Desktop/project/site/functions/helper_functions.py" in uploaded_file_type
12. f = file.image.read(1024)
Exception Type: AttributeError at /post/
Exception Value: 'JpegImageFile' object has no attribute 'read'
完整型号:
class Post(models.Model):
user = models.ForeignKey(User, blank=True, null=True)
title = models.TextField(max_length=95)
image = models.FileField(null=True, blank=True)
以及伴随的PostForm
:
class PostForm(forms.ModelForm):
title = forms.TextInput(attrs={'placeholder': 'title'})
class Meta:
model = Post
fields = [
'user',
'title',
'image',
]
views.py
def post(request):
if request.user.is_authenticated():
form_post = PostForm(request.POST or None, request.FILES or None)
if form_post.is_valid():
instance = form_post.save(commit=False)
if instance.image:
filename = instance.image
instance.image = Image.open(instance.image)
instance.image.thumbnail((220, 130), Image.ANTIALIAS)
instance.image.save(filename, quality=60)
instance.save()
return HttpResponseRedirect('/home/')
else:
form_post = PostForm()
context = {
'form_post': form_post,
}
return render(request, 'post/post.html', context)
else:
return HttpResponseRedirect("/accounts/signup/")
下面的代码:
if instance.image:
im = Image.open(instance.image)
print("Filename:", im.filename) #doesn't print anything
thumb = im.thumbnail((220, 130), Image.ANTIALIAS)
thumb.save(im.filename, quality=60)
返回一个AttributeError
:'NoneType' object has no attribute 'save'
。我相信这是因为im.filename
什么都不打印。知道为什么吗?
另一种方法:
if instance.image:
im = Image.open(instance.image)
thumb = im.thumbnail((220, 130), Image.ANTIALIAS)
thumb_io = BytesIO()
thumb.save(thumb_io, im.format, quality=60)
instance.image.save(im.filename, ContentFile(thumb_io.get_value()), save=False)
还返回AttributeError
:'NoneType' object has no attribute 'save'
,在此行:thumb.save(thumb_io, im.format, quality=60)
。不知道为什么吗?
问题答案:
您必须传递djangoFile
对象的实例FileField.save()
才能更改文件字段的内容。它的工作方式与其他类型的模型字段有所不同。
FieldFile.save(名称,内容,保存=真)
此方法采用文件名和文件内容,并将它们传递到该字段的存储类,然后将存储的文件与model字段关联。如果要手动将文件数据与模型上的FileField实例相关联,则使用save()方法来保留该文件数据。
from PIL import Image
from django.core.files.base import ContentFile
if instance.image:
im = Image.open(instance.image)
im.thumbnail((220, 130), Image.ANTIALIAS)
thumb_io = BytesIO()
im.save(thumb_io, im.format, quality=60)
instance.image.save(im.filename, ContentFile(thumb_io.getvalue()), save=False)
instance.save()
但是,如果您不使用远程文件存储后端,则可以覆盖文件本身。该文件是在您调用时创建的form.save()
。由于您使用相同的文件名和位置,因此您实际上不必触摸模型或告诉django您正在弄乱文件本身。
if instance.image:
im = Image.open(instance.image)
im.thumbnail((220, 130), Image.ANTIALIAS)
im.save(im.filename, quality=60)