我正在Django应用程序中处理作物图像
Myform:
class UploadImageForm(forms.ModelForm):
x = forms.FloatField(widget=forms.HiddenInput())
y = forms.FloatField(widget=forms.HiddenInput())
width = forms.FloatField(widget=forms.HiddenInput())
height = forms.FloatField(widget=forms.HiddenInput())
primaryphoto = forms.ImageField(required=False,
error_messages={'invalid': _("Image files only")}, widget=forms.FileInput)
class Meta:
model = User
fields = ['primaryphoto', 'x', 'y', 'width', 'height',]
def save(self):
user = super(UploadImageForm, self).save()
x = self.cleaned_data.get('x')
y = self.cleaned_data.get('y')
w = self.cleaned_data.get('width')
h = self.cleaned_data.get('height')
image = Image.open(user.primaryphoto)
cropped_image = image.crop((x, y, w + x, h + y))
resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
resized_image.save(user.primaryphoto.path)
return user
myview:
def upload_image(request):
if request.method == 'POST':
form = UploadImageForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
form.save()
return redirect('/profile')
else:
form = UploadImageForm(instance=request.user)
return render(request, 'student/uploadimageform.html', {'form': form})
storage_backend.py:
from storages.backends.s3boto3 import S3Boto3Storage
class MediaStorage(S3Boto3Storage):
location = 'media'
file_overwrite = False
但是,当我将其上传到AWS上运行时,收到了错误消息backend does not support absolute paths (in reference to primaryphoto.path in the form where the photo is cropped)
。我想知道我必须进行哪些更改才能使其与S3一起使用。我发现一些资源说将primaryphoto.path更改为primaryphoto.name,但这对我没有用。我想知道您是否有解决此问题的建议?
此处图像已上传到S3存储桶,但问题引发以上错误。请任何人帮助我。预先感谢...
编辑答案:
def save(self):
user = super(UploadImageForm, self).save()
x = self.cleaned_data.get('x')
y = self.cleaned_data.get('y')
w = self.cleaned_data.get('width')
h = self.cleaned_data.get('height')
try:
image = Image.open(user.primaryphoto)
cropped_image = image.crop((x, y, w + x, h + y))
resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
resized_image.save(user.primaryphoto.path)
except:
pass
return user
这里是引发错误,但是图像正在本地上载并且S3存储桶正确...用于处理路径错误,我正在使用try(块除外)
答案 0 :(得分:1)
这个对我有用。只需替换表单中的save()方法即可。
from django.core.files.storage import default_storage as storage
def save(self):
user = super(UploadImageForm, self).save()
x = self.cleaned_data.get('x')
y = self.cleaned_data.get('y')
w = self.cleaned_data.get('width')
h = self.cleaned_data.get('height')
image = Image.open(user.primaryphoto)
cropped_image = image.crop((x, y, w + x, h + y))
resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
fh = storage.open(user.primaryphoto.name, "w")
picture_format = 'png'
resized_image.save(fh, picture_format)
fh.close()
resized_image.save(user.primaryphoto.path)
return user
答案 1 :(得分:1)
对于那些从google重定向到这里的人,这里的代码已根据@Alexandar Dimitro的答案以及此页面上的其他注释进行了测试,并在AWS上运行。
from django.core.files.storage import default_storage as storage
def save(self):
user = super(UploadImageForm, self).save()
x = self.cleaned_data.get('x')
y = self.cleaned_data.get('y')
w = self.cleaned_data.get('width')
h = self.cleaned_data.get('height')
image = Image.open(user.primaryphoto)
cropped_image = image.crop((x, y, w + x, h + y))
resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
fh = storage.open(user.primaryphoto.name, "wb")
picture_format = 'png'
resized_image.save(fh, picture_format)
fh.close()
return user
答案 2 :(得分:0)
请尝试以下操作。
我没有测试它,但是一些解释会很好:我们将图像转换为字符串缓冲区,以便使用裁剪后的图像创建Django InMemoryUploadedFile
。在这种情况下,我们不使用path
。试试看,让我知道您还会遇到其他错误。
import os
from io import BytesIO as StringIO # python3
from django.core.files.uploadedfile import InMemoryUploadedFile
def save(self):
user = super(UploadImageForm, self).save()
x = self.cleaned_data.get('x')
y = self.cleaned_data.get('y')
w = self.cleaned_data.get('width')
h = self.cleaned_data.get('height')
image = Image.open(user.primaryphoto)
cropped_image = image.crop((x, y, w + x, h + y))
resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
filename = os.path.splitext(resized_image.name)[0]
output = StringIO()
resized_image.save(output, format='JPEG', quality=95)
output.seek(0) #Change the stream position to the given byte offset.
new_image = InMemoryUploadedFile(output,'ImageField',\
"%s.jpg" % filename , 'image/jpeg', output.__sizeof__(), None)
user.primaryphoto = new_image
user.save()
return user
答案 3 :(得分:0)
所以,由于我刚加入堆栈溢出,所以我的声誉有点低。但是我想说这个问题已经存在了大约一个星期,我才解决了!
Alexandar Dimitrov的回答极大地帮助了我!但是,他的回答中有一个小错误。您需要删除“回访用户”上方的最后一行。
也就是说,删除以下行:“ resized_image.save(user.primaryphoto.path)”。遗留在那似乎是一个错误。
-祝一切顺利
答案 4 :(得分:0)
对我来说 default.storage.write() 不起作用,image.save() 不起作用,这个起作用了。如果有人仍然感兴趣,请查看此代码。我为缩进道歉。我的项目使用的是 Cloudinary 和 Django 小项目。
from io import BytesIO
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage as storage
def save(self, *args, **kargs):
super(User, self).save(*args, **kargs)
# After save, read the file
image_read = storage.open(self.profile_image.name, "r")
image = Image.open(image_read)
if image.height > 200 or image.width > 200:
size = 200, 200
# Create a buffer to hold the bytes
imageBuffer = BytesIO()
# Resize
image.thumbnail(size, Image.ANTIALIAS)
# Save the image as jpeg to the buffer
image.save(imageBuffer, image.format)
# Check whether it is resized
image.show()
# Save the modified image
user = User.objects.get(pk=self.pk)
user.profile_image.save(self.profile_image.name, ContentFile(imageBuffer.getvalue()))
image_read = storage.open(user.profile_image.name, "r")
image = Image.open(image_read)
image.show()
image_read.close()