Django:从表单问题上传 PIL 图片
Django: PIL image upload from form issue
Django:图片上传问题
Python: 3.5
Django: 1.11
我正在编写一个简单的新闻应用程序,它会将图像作为文章的一部分。我选择使用 Django Forms 提供的 clean_(field name)
函数修改图像创建缩略图以存储在表单中。
我遇到的问题是,在完成提交和 clean_image
函数后,ImageField 验证将我踢回并显示 file extension " is not allowed
错误。
我知道问题出在 clean_image
函数之后,我保存了 PIL 图像,然后将其交还给 Django ContentFile 进行处理。任何帮助都会很棒。
表格:
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
型号:
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
所以我找到了问题所在。我是对的,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
Django:图片上传问题
Python: 3.5
Django: 1.11
我正在编写一个简单的新闻应用程序,它会将图像作为文章的一部分。我选择使用 Django Forms 提供的 clean_(field name)
函数修改图像创建缩略图以存储在表单中。
我遇到的问题是,在完成提交和 clean_image
函数后,ImageField 验证将我踢回并显示 file extension " is not allowed
错误。
我知道问题出在 clean_image
函数之后,我保存了 PIL 图像,然后将其交还给 Django ContentFile 进行处理。任何帮助都会很棒。
表格:
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
型号:
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
所以我找到了问题所在。我是对的,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