django后端不支持绝对路径

时间:2018-10-18 05:36:00

标签: django amazon-s3 image-uploading

我正在Django应用程序中处理作物图像

使用本教程Crop Images in 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(块除外)

5 个答案:

答案 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()