Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用Django'跟踪图像类型;s文件字段_Python_Django_Upload_Pillow - Fatal编程技术网

Python 使用Django'跟踪图像类型;s文件字段

Python 使用Django'跟踪图像类型;s文件字段,python,django,upload,pillow,Python,Django,Upload,Pillow,我的模型有一个接受图像的文件字段。我用Pillow验证它们,并强制使用图像格式,但我还想用适当的扩展名保存图像文件。例如,如果上载名为foo.gif的JPEG图像,我希望将其保存为000.jpg,其中数字是模型中的另一个字段 我在哪里存储图像格式,以便以后在我的upload\u tocallable中重用它以生成上载路径 class ImageField(models.FileField): default_error_messages = { 'invalid_imag

我的模型有一个接受图像的
文件字段
。我用Pillow验证它们,并强制使用图像格式,但我还想用适当的扩展名保存图像文件。例如,如果上载名为
foo.gif
的JPEG图像,我希望将其保存为
000.jpg
,其中数字是模型中的另一个字段

我在哪里存储图像格式,以便以后在我的
upload\u to
callable中重用它以生成上载路径

class ImageField(models.FileField):
    default_error_messages = {
        'invalid_image': "Upload a valid image. The file you uploaded was either not an image or a corrupted image.",
        'invalid_format': "Upload an image in a valid format. The supported formats are JPEG and PNG.",
    }

    def to_python(self, data):
        f = super(ImageField, self).to_python(data)

        if f is None:
            return None

        if hasattr(data, 'temporary_file_path'):
            file = data.temporary_file_path()
        elif hasattr(data, 'read'):
            file = BytesIO(data.read())
        else:
            file = BytesIO(data['content'])

        try:
            image = Image.open(file)
            image.verify()

            if image.format not in {'PNG', 'JPEG'}:
                raise ValidationError(self.error_messages['invalid_format'], code='invalid_format')
        except Exception:
            raise ValidationError(self.error_messages['invalid_image'], code='invalid_image')

        if hasattr(f, 'seek') and callable(f.seek):
            f.seek(0)

        return f

class Image(models.Model):
    number = models.PositiveSmallIntegerField()
    image = ImageField(upload_to=self.upload_path)

    def upload_path(self, instance, upload_filename):
        return ???

真的,据我所知,你甚至不需要使用枕头(除非你没有发布更多的项目)。您只需定义一个,然后在检索时访问
文件字段
。我建议使用这种方法,因为99%的时间都是通过使用文件对象本身、从文件名确定信息,或者(在某些罕见的情况下)使用
子流程执行一些命令行魔术来找到文件及其格式的

在任何情况下,这里都有一个存储示例:

from django.core.files.storage import Storage

class MyStorage(Storage):
    ...
    def get_valid_name(name):
        return name.replace('gif', 'jpg')
    ...
这就是你可能有点困惑的地方。Django有自己的存储引擎,可以自动将文件写入您的
MEDIA\u ROOT
目录。因此,您的代码片段

def upload_path(self, instance, upload_filename):
    return ???

是否冗余(如果您定义自己的存储,即;)现在是否更有意义django.core.files.storage.storage就是来帮你的。

啊,我明白了。对不起,我不明白

枕头提供一个包含图像信息的枕头。可能是你想要的财产

我甚至自己做了一个小测试,看看扩展是否重要:

user@host:~/Images$ cp myimage.jpg myimage.gif
user@host:~/Images$ cp myimage.jpg myimage.txt  # Extreme test!
user@host:~/Images$ python
Python 2.7.4 (default, Apr 19 2013, 18:28:01) 
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from PIL import Image
>>> im = Image.open('/home/user/Images/myimage.jpg')
>>> im.format
'JPEG'
>>> im = Image.open('/home/user/Images/myimage.gif')
>>> im.format
'JPEG'

不,没关系。看起来不错<强>☺

首先,上面粘贴的代码片段来自django表单。注意,Django有两种字段类:Model字段和Form字段。它们的名称通常相同,但实现和目的却完全不同。在您的示例中,您试图在自定义模型字段中使用从表单字段复制的代码

您真正感兴趣的代码如下:-这是提取图像维度的片段。然后在这里使用Mixin类
ImageFile
:在
ImageFieldFile
中。后者随后用作
ImageField
模型字段类中的属性类

因此,您只需要:

  • 复制
    django/core/files/images.py
    ,并对其进行修改,不仅提取维度,还提取文件类型(例如,您将此mixin
    ImageFileWithType
  • 通过提供自定义mixin来覆盖
    ImageFieldFile
  • 覆盖
    ImageField
    class,替换其中的属性类
  • 从\u自定义\u字段\u模块导入ImageFileWithType
    从django.db.models.fields导入ImageFieldFile,ImageField
    类ImageFieldFileWithType(ImageFileWithType,ImageFieldFile):
    “”“作为`ImageFileWithType`mixin在开头,
    它覆盖默认的mixin“”
    通过
    类别ImageFieldWithType(ImageField):
    attr_class=ImageFieldFileWithType
    
    然后只需在模型中使用此模型字段!请注意,如果您使用的是南方迁移,则在处理自定义模型字段时需要特别小心


    希望,这有帮助

    我不确定我是否能很好地解释我的问题。即使使用存储系统,如何在不查看扩展名的情况下访问映像文件的类型?只要假设上传的图像的文件名就是
    image
    ,我需要弄清楚它是否是JPG、PNG,以及它是否真的是图像。完成后,我可以确定它的完整文件名。是的,如果您查看我的代码,您可以看到我正在使用此属性验证图像。看起来Django的
    ImageFileField
    实际上是计算每个图像的宽度和高度,并将结果缓存在内存中,而不是数据库中,所以我只能在表单中执行此操作。首先,为什么要使用
    FileField
    ,而不是Django中存在的
    ImageField
    ?见: