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
,并对其进行修改,不仅提取维度,还提取文件类型(例如,您将此mixinImageFileWithType
)
通过提供自定义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
?见: