Django:从表单问题上传PIL图像

时间:2017-05-12 17:23:46

标签: python django forms pillow

Django:图片上传问题

Python:3.5

Django:1.11

我正在编写一个简单的新闻应用程序,它将把图像作为文章的一部分。我已经选择修改图像,创建一个缩略图,以便使用Django Forms提供的clean_image函数存储在表单中。

我遇到的问题是,在完成提交和file extension " is not allowed功能后,ImageField验证会让我回复,并显示clean_image错误。

我知道在保存PIL图像后问题来自from django.conf import settings from django.core.files.base import ContentFile from django.utils.translation import ugettext_lazy as _ from .models import News from ironcsd.validators import MimetypeValidator from datetime import date from PIL import Image, ImageEnhance from io import StringIO, BytesIO import hashlib, mimetypes import os, io import logging, logging.config logger = logging.getLogger(__name__) class NewsForm(forms.ModelForm): class Meta: model = News widgets = { 'details': forms.Textarea(attrs={'id': 'smde-editor'}), } fields = ('title','details','image') def clean_image(self): image = self.cleaned_data.get('image') md5 = hashlib.md5() md5.update(repr(image.name).encode('utf-8')) file_name = md5.hexdigest() if image._size > 30 * 1024 * 1024: raise forms.ValidationError(_('File is too big.'), code='invalid') image = Image.open(image) if image.size[0] < 1024 or image.size[1] < 1024: raise forms.ValidationError(_('Your image needs to be at least 1024x1024.')) image.thumbnail([1024,1024], Image.ANTIALIAS) image_string = io.BytesIO() image.save(image_string, image.format) image = ContentFile(image_string.getvalue(), file_name) return image 函数,然后将其交回Django ContentFile进行处理。任何帮助都会很棒。

形式:

from django.db import models
from django.urls import reverse, reverse_lazy
from ironcsd.models import Audit

class News(Audit):
    title = models.CharField(max_length=255)
    details = models.TextField()
    image = models.ImageField(upload_to='news/%Y/%m/')

    class Meta:
        verbose_name_plural = "news"

    def __str__(self):
        return self.title

型号:

padding-left

1 个答案:

答案 0 :(得分:1)

所以我找到了问题。我认为ContentFile是个问题。在ContentFile中,您需要提供io值和文件名。

ContentFile(image_io.getvalue(), image_name)

在image_name中,您需要确保图像具有文件扩展名(bmp,png,gif等),以便在转换回django对象时,文件可以通过适当的验证。所以代码答案如下。

我从清理后的图像名称创建一个散列文件名。然后我创建了一个名为image_name的变量,它接受了file_name并添加了PIL图像格式作为扩展名。

image_name = '{}.{}'.format(file_name,image.format)

然后我在我的ContentFile中使用了这个image_name,它在视图中将一个正确的文件传递给了我的form_valid。

完成代码:

class NewsForm(forms.ModelForm):

    class Meta:
        model = News
        widgets = {
            'details': forms.Textarea(attrs={'id': 'smde-editor'}),
        }
        fields = ('title','details','image')


    def clean_image(self):
        image = self.cleaned_data.get('image')
        md5 = hashlib.md5()
        md5.update(repr(image.name).encode('utf-8'))
        file_name = md5.hexdigest()

        if image._size > 30 * 1024 * 1024:
            raise forms.ValidationError(_('File is too big.'), code='invalid')

        image = Image.open(image)

        if image.size[0] < 1024 or image.size[1] < 1024:
            raise forms.ValidationError(_('Your image needs to be at least 1024x1024.'))

        if image.format not in ('BMP','PNG','JPEG','GIF'):
            raise forms.ValidationError(_("Unsupported image type. Please uplod a bmp, png, jpeg, or gif."), code='invalid')

        image.thumbnail([1024,1024], Image.ANTIALIAS)
        image_io = io.BytesIO()
        image.save(image_io, format=image.format)
        image_name = '{}.{}'.format(file_name,image.format)
        image = ContentFile(image_io.getvalue(), image_name)

        return image