带有PIL的Django - '_io.BytesIO'对象没有属性'name'

时间:2018-03-10 21:51:39

标签: django python-imaging-library

我正在使用PIL在保存之前调整上传的照片大小。请注意,我正在使用formsets上传图片。我正在使用BytesIO打开文件。在最后一步,我收到错误 - '_io.BytesIO' object has no attribute 'name'。为什么是这样?

def fsbo_create_listing(request):
    PhotoFormSet = formset_factory(OwnerListingPhotoForm, extra=15)
    if request.method == 'POST':
        form = OwnerListingForm(request.POST)
        photo_formset = PhotoFormSet(request.POST, request.FILES)
        if form.is_valid() and photo_formset.is_valid():
            form.instance.user = request.user
            form.save()
            for i in photo_formset:
                if i.instance.pk and i.instance.photo == '':
                    i.instance.delete()
                elif i.cleaned_data:
                    temp = i.save(commit=False)
                    temp.listing = form.instance
                    temp.save() # Where the error happens
def clean_photo(self):
    picture = self.cleaned_data.get('photo')
    # I had to import ImageFieldFile.  If picture is already uploaded, picture would still be retrieved as ImageFieldFile.  The following line checks the variable type of `picture` to determine whether the cleaning should proceed.
    if type(picture) != ImageFieldFile:
        image_field = self.cleaned_data.get('photo')
        image_file = BytesIO(image_field.read())
        image = Image.open(image_file)
        image = ImageOps.fit(image, (512,512,), Image.ANTIALIAS)
        image_file = BytesIO()
        image.save(image_file, 'JPEG', quality=90)
        image_field.file = image_file
        #if picture._size > 2*1024*1024:
            #raise ValidationError("Image file too large.  Max size is 2MB.")
    return picture
class OwnerListingPhoto(models.Model):

    listing = models.ForeignKey(OwnerListing, on_delete=models.CASCADE, related_name='owner_listing_photo')
    photo = models.ImageField(upload_to=owner_listing_folder_name)

1 个答案:

答案 0 :(得分:2)

问题是新版本的Django默认使用MemoryFileUploadHandler,它不会创建临时文件,因此没有文件“name”。 See related Django ticket.

您可能需要稍微修改一下代码才能使其正常工作,但您至少可以通过设置来获取name属性:

FILE_UPLOAD_HANDLERS = [
    'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]

在settings.py文件中。

您可能会发现我用来解决几乎完全相同的问题的代码。

def clean_logo_file(self):
    logo_file_field = self.cleaned_data.get('logo_file')
    if logo_file_field:
        try:
            logo_file = logo_file_field.file
            with Image.open(logo_file_field.file.name) as image:
                image.thumbnail((512, 512), Image.ANTIALIAS)
                image.save(logo_file, format=image.format)
                logo_file_field.file = logo_file
                return logo_file_field
        except IOError:
            logger.exception("Error during image resize.")

有关upload handlers的其他信息。