Django - 使ModelForm(ImageField)只接受某些类型的图像

时间:2014-07-14 05:55:10

标签: django validation file-type django-models

我正在使用Pillow 2.3.0和Django,我的models.py中有一个ImageField,如下所示:

class UserImages(models.Model):
    user = models.ForeignKey(User)
    photo = models.ImageField(upload_to=get_file_path)

我有一个这样的表格:

class UploadImageForm(forms.ModelForm):
    class Meta:
        model = UserImages
        fields = ['photo']

我如何制作它以便UploadImageForm只接受png' s和jpeg' s?我尝试的是将这个干净的方法添加到表单中:

def clean_photo(self):
    photo = self.cleaned_data.get('photo', False)
    if photo:
        fileType = photo.content_type
        if fileType in settings.VALID_IMAGE_FILETYPES: #png and jpeg
            return photo
    raise forms.ValidationError('FileType not supported: only upload jpegs and pngs.')

但是根据此文档(https://docs.djangoproject.com/en/1.5/topics/http/file-uploads/#uploadedfile-objects),它表示"您仍然需要验证该文件是否包含内容类型标题所声称的内容 - 信任但要验证'。"如何验证用户是否上传了他声称要上传的文件类型?

1 个答案:

答案 0 :(得分:4)

ImageField验证程序已验证上传的文件是Pillow支持的有效图像文件。这足以防止任何恶意代码注入 - 最糟糕的情况是有人上传的文件扩展名与文件格式不同。

我通常不会验证上传的图片是否确实是其描绘的格式。只要它是有效的图像文件,并且文件扩展名在我允许的扩展名中,我接受上传的文件。

但是,您可以轻松覆盖clean_photo方法以确定并验证实际文件类型:

from django.utils.image import Image

def clean_photo(self):
    photo = self.cleaned_data.get(['photo'])
    if photo:
        format = Image.open(photo.file).format
        photo.file.seek(0)
        if format in settings.VALID_IMAGE_FILETYPES:
            return photo
    raise forms.ValidationError(...)

photo.file.seek(0)部分很重要,如果没有它,您在保存文件时会遇到问题!!

请注意,format不一定等于内容类型或扩展名:在.png的情况下,它是'PNG',在.jpg的情况下,它是&'JPEG' #39; s Image.open。我不知道其他格式是否也适用;你必须自己测试一下。

timeit不会加载整个文件内容,只加载标题,因此这种方法非常快。使用.png和随机format = Image.open(g.photo).format g.photo.seek(0) 文件,我运行以下代码1,000,000次:

{{1}}

这段代码的平均时间是0.0001秒,所以是的,闪电般快。