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

use*_*875 2 python django validation django-models django-forms

我将 Pillow 2.3.0 与 Django 一起使用,并且在 models.py 中有一个 ImageField,如下所示:

\n\n
class UserImages(models.Model):\n    user = models.ForeignKey(User)\n    photo = models.ImageField(upload_to=get_file_path)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我有一个像这样的表格:

\n\n
class UploadImageForm(forms.ModelForm):\n    class Meta:\n        model = UserImages\n        fields = [\'photo\']\n
Run Code Online (Sandbox Code Playgroud)\n\n

如何使 UploadImageForm 只接受 png 和 jpeg?我尝试的是将这个干净的方法添加到表单中:

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

但根据本文档(https://docs.djangoproject.com/en/1.5/topics/http/file-uploads/#uploadedfile-objects),它说“您仍然需要验证该文件是否包含内容类型标头声明 \xe2\x80\x93 \'信任但验证\'的内容。” 如何验证用户确实上传了他声称上传的文件类型?

\n

knb*_*nbk 6

验证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(...)
Run Code Online (Sandbox Code Playgroud)

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

请注意,format不一定等于内容类型或扩展名:在.png它的情况下是'PNG',在.jpg它的情​​况下是'JPEG'。不知道其他格式是否也效仿;你必须亲自测试一下。

Image.open不会加载整个文件内容,仅加载标题,因此此方法相当快。使用timeit随机.png文件,我已运行以下代码 1,000,000 次:

format = Image.open(g.photo).format
g.photo.seek(0)
Run Code Online (Sandbox Code Playgroud)

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