我正在使用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)
。不确定为什么呢?
答案 0 :(得分:6)
您必须将django的File
对象的实例传递给FileField.save()
才能更改文件字段的内容。它与其他类型的模型字段有点不同。
FieldFile.save(name,content,save = True)
此方法获取文件名和文件内容并将其传递给 该字段的存储类,然后将存储的文件与 模型领域。如果要手动关联文件数据 模型上的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.get_value()), 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)