Django的图像字段
项目描述
基于django-versatileimagefield,但有一些重要区别
代码量保持在最小。django-versatileimagefield的代码量(不包含测试)要多几倍。
有目的地使在渲染代码中按需生成图像变得困难。相反,图像在模型保存时生成,也可以通过运行管理命令process_imagefields生成。
django-imagefield不依赖于快速存储或缓存来保持速度,至少在图像宽度和高度保存在数据库中的情况下是这样。这其中的一个重要部分是永远不检查处理后的图像是否在热路径中存在(除非你强制它)。
当图像数据不完整或由于某些原因无法由 Pillow 处理时,django-imagefield 会早期失败。
通过将 auto_add_fields=True 添加到字段,而不是无聊且冗长地自己添加,django-imagefield 允许通过模型添加宽度、高度和 PPOI(主要兴趣点)字段。
替换现有的 django-versatileimagefield 使用需要以下步骤
from imagefield.fields import ImageField as VersatileImageField, PPOIField
可以通过提供 ImageField(formats=...) 或添加 IMAGEFIELD_FORMATS 设置来指定图像大小。后者如果给出,将覆盖前者。
当使用下面的 IMAGEFIELD_FORMATS 设置时,将模板代码转换为访问新属性(例如,使用 instance.image.square 而不是 instance.image.crop.200x200)。
当使用 django-imagefield 和 PPOI 时,确保将 PPOI 字段也添加到 ModelAdmin 或 InlineModelAdmin 字段集中,否则你只会看到图像,但不会有 PPOI 选择器。与 django-versatileimagefield 相反,PPOI 字段本身是可编辑的,这避免了除其他复杂性之外,还有行内表单更改检测的陷阱。
将 "imagefield" 添加到 INSTALLED_APPS。
如果你之前使用了例如 instance.image.crop.200x200 和 instance.image.thumbnail.800x500,你应该添加以下设置
IMAGEFIELD_FORMATS = {
# image field path, lowercase
'yourapp.yourmodel.image': {
'square': ['default', ('crop', (200, 200))],
'full': ['default', ('thumbnail', (800, 500))],
# The 'full' spec is equivalent to the following format
# specification in terms of image file produced (the
# resulting file name is different though):
# 'full': [
# 'autorotate', 'process_jpeg', 'process_png',
# 'process_gif', 'autorotate',
# ('thumbnail', (800, 500)),
# ],
# Note that the exact list of default processors may
# change in the future.
},
}
运行 ./manage.py process_imagefields --all 一次后,你现在可以在模板中使用 instance.image.square 和 instance.image.thumbnail。请注意,出于设计考虑,image 文件的属性不会检查缩略图是否存在。
安装
从 PyPI 安装: pip install django-imagefield。
然后,将 imagefield 添加到项目的 INSTALLED_APPS
# settings.py INSTALLED_APPS = [ ... "imagefield", ... ]
使用
一旦将 imagefield 添加到 INSTALLED_APPS,就可以像往常一样将 ImageField 实例添加到 Django 模型中
from django.db import models from imagefield.fields import ImageField class ImageModel(models.Model): image = ImageField( upload_to="images", formats={ "thumb": ["default", ("crop", (300, 300))], "desktop": ["default", ("thumbnail", (300, 225))], }, auto_add_fields=True, )
formats 确定创建的处理的图像的大小。
auto_add_fields 将自动添加 image_width、image_height 和 image_ppoi 字段,如果模型中不存在这些字段。(使用的字段名称是可以自定义的。有关详细信息,请参阅 ImageField 构造函数。)
Django Admin 会自动使用选择 PPOI 的小部件。
要在你自己的 Django 表单中使用 ImageField,你应该确保将 image_ppoi 字段添加到表单
from django.form import modelform_factory form_cls = modelform_factory(ImageModel, fields=['image', 'image_ppoi'])
你应该确保将 form.media 添加到你的页面模板的 <head> 中。
在你的模板中检索图像 URL,例如,instance.image.thumb。
图像处理器
django-imagefield 使用一个类似 Django 中间件模型的图像处理管道。
以下是一些内置的处理器
autorotate:通过读取 EXIF 数据自动旋转图像。
process_jpeg:将非 RGB 图像转换为 RGB,激活渐进式编码并将质量设置为更高的 90。
process_png:将调色板 PNG 图像转换为 RGBA。
process_gif:在调整大小后的图像中保留透明度和调色板数据。
preserve_icc_profile:正如其名。
thumbnail:调整图像大小,使其不超过边界框。
crop:裁剪图像到指定的尺寸,如果提供,也会考虑PPOI(主要兴趣点)信息。
default:结合了autorotate、process_jpeg、process_gif、process_png和preserve_icc_profile。未来可能还会添加其他默认处理器。建议使用default而不是逐个添加处理器。
处理器可以通过其名称单独指定,或者如果它们需要参数,可以使用包含处理器名称和其余参数的位置参数的元组。
您可以轻松注册自己的处理器,甚至可以覆盖内置处理器。
from imagefield.processing import register
# You could also write a class with a __call__ method, but I really
# like the simplicity of functions.
@register
def my_processor(get_image, ...):
def processor(image, context):
# read some information from the image...
# or maybe modify it, but it's mostly recommended to modify
# the image after calling get_image
image = get_image(image, context)
# modify the image, and return it...
modified_image = ...
# maybe modify the context...
return modified_image
return processor
处理器名称直接来自注册的对象。
一个将图像转换为灰度的示例处理器如下所示
from PIL import ImageOps
from imagefield.processing import register
@register
def grayscale(get_image):
def processor(image, context):
image = get_image(image, context)
return ImageOps.grayscale(image)
return processor
现在在需要使用它的图像的处理规范中包含"grayscale"。
处理上下文
上下文是一个包含以下属性的命名空间(您可以根据需要添加自己的属性)
processors:处理器列表。
name:相对于其存储根的结果图像名称。
extension:源和目标文件的扩展名。
ppoi:作为介于0和1之间的两个浮点数的列表的主要兴趣点。
save_kwargs:传递给PIL.Image.save的关键字参数字典。
在运行处理器时无法再修改ppoi、extension、processors和name属性。在某些情况下,extension和name甚至可能不存在。
如果您想修改扩展名或文件类型,或者创建基于在配置设置时未知的事实不同的处理流程,可以使用可调用的函数而不是处理器列表。该可调用的函数将接收字段文件和上下文实例,并必须至少设置上下文的processors属性为合理值。以下是一个始终返回JPEG缩略图的图像字段的示例
from imagefield.processing import register
@register
def force_jpeg(get_image):
def processor(image, context):
image = get_image(image, context)
context.save_kwargs["format"] = "JPEG"
context.save_kwargs["quality"] = 90
return image
return processor
def jpeg_processor_spec(fieldfile, context):
context.extension = ".jpg"
context.processors = [
"force_jpeg",
"autorotate",
("thumbnail", (200, 200)),
]
class Model(...):
image = ImageField(..., formats={"thumb": jpeg_processor_spec})
当然,您也可以通过其fieldfile.instance属性访问模型实例,并使用这些信息来自定义管道。
设置
django-imagefield支持一些设置来定制其行为。
默认设置如下
# Automatically generate and delete images when saving and deleting models.
# Can either be a boolean or a list of "app.model.field" strings. It's
# recommended to set this to False for some types of batch processing since
# updating the images may slow things down a lot.
IMAGEFIELD_AUTOGENERATE = True
# The image field doesn't generally need a cache, but it's definitely
# useful for admin thumbnails and the versatile image proxy. The timeout
# can be configured here. By default, a random duration between 170 and
# 190 days is used, so that the cache doesn't expire at the same time for
# all images when running several server processes.
IMAGEFIELD_CACHE_TIMEOUT = lambda: randint(170 * 86400, 190 * 86400)
# See above.
IMAGEFIELD_FORMATS = {}
# Whether images should be deeply validated when saving them. It can be
# useful to opt out of this for batch processing.
IMAGEFIELD_VALIDATE_ON_SAVE = True
# Errors while processing images lead to exceptions. Sometimes it's
# desirable to only log those exceptions but fall back to the original
# image. This setting let's you do that. Useful when you have many images
# which haven't been verified by the image field.
IMAGEFIELD_SILENTFAILURE = False
# Add support for instance.image.crop.WxH and instance.image.thumbnail.WxH
# An easier path to migrate away from django-versatileimagefield.
IMAGEFIELD_VERSATILEIMAGEPROXY = False
# How many folders and subfolders are created for processed images. The
# default value is 1 for backwards compatibility, it's recommended to
# increase the value to 2 or 3.
IMAGEFIELD_BIN_DEPTH = 1
开发
django-imagefield使用pre-commit来保持代码整洁和格式化。
构建文档和运行测试套件的最简单方法也是使用tox
tox -e docs # Open docs/build/html/index.html
tox -l # To show the available combinations of Python and Django