前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >服务端图片处理神器 Django-imagekit 介绍

服务端图片处理神器 Django-imagekit 介绍

作者头像
the5fire
发布2019-03-01 10:56:51
1K0
发布2019-03-01 10:56:51
举报

这两天做了一个定制django-imagekit生成图片名称的任务,本来想简单写写《如何定制Django-imagekit的ImageSpecField名称规则》,但是想到这个东西这么吊,还是多废话几句吧。

先说说场景,无论是做哪种业务,但凡是涉及到图片的,一定会有裁图的需求。但是裁图的需求又分好几种,主要的两种是:一种是被动裁图,可以裁出各种尺寸或限定的几种尺寸;另外一种是主动裁图,裁出固定的几种尺寸。

根据以往的项目实践中,我们往往是采用前一种做法,通过nignx的一个裁图模块image_filter,根据URL的参数来裁图,比方说,有原图:/images/the5fire.png, 通过请求 /images/the5fire.png/90x90 就可以得到一个90x90的方图,这是一例,被动裁图——接受到用户请求之后才处理图片。

另外一种是主动裁图,通过nginx的模块也能做,做法就是程序先自动去请求一遍。这种方式的另外一种做法就是自己在程序中裁图,对于读多写少的应用来说还挺合适。在Python程序中怎么处理裁图的需求呢?有个Pillow的库,也是很强大。如果在Django中处理,那就要考虑是不是有人已经在Pillow上做好了更符合Django流程的封装了,Django-imagekit就是这么个东西!

按照我们的需求,提供几种比例相同尺寸不同的图片,用Django-imagekit完全满足需求,当然最重要的是,很易用。

举个例子,定义个Model:

代码语言:javascript
复制
from django.db import models
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill

class Author(models.Model):
    avator = models.ImageField(
        upload_to="horizontal", blank=True,
        verbose_name="原图")
    avator_90x90 = ImageSpecField(
        source="avator", processors=[ResizeToFill(90, 90)],
        format='JPEG', options={'quality': 95})
    avator_30x30 = ImageSpecField(
        source="avator", processors=[ResizeToFill(30, 30)],
        format='JPEG', options={'quality': 95})

    # ImageSpecField不会生成数据库中的表

这样定义完之后,在xadmin后台我只需要上传一个原图,在访问的时候会自动生成90x90和30x30的图,访问的时候只需要author.avator_90x90.url即可。当然在模板上Django-imagekit也提供的一些tags,可以直接在模板中进行图片处理。

之前说的是主动裁图的方式,imagekit提供了几种生成图的策略:内容获取,路径访问,原图保存。主动裁图就是使用原图保存时进行生成的策略。另外值得一提的是,它还支持异步的方式来生成图片,需要用到Celery。

一开始有说到自定义生成图的路径的问题。默认情况下,imagekit使用 imagekit.cachefiles.namers.source_name_as_path 来生成图片的路径。大体逻辑是,根据你设置的参数:processors,format,options进行pickle,把数据写到一个内存文件中,然后根据文件内容做一个md5,作为生成这个尺寸图片的名称。这么说比较抽象,还是举个例子:原图:/image/the5fire.png 生成图 /CACHE/images/the5fire/123dadwdniijonsd.jpg,这不是实际的生成结果,只是示例,最后的 123xxxsd 可以当做那个md5的值,当然前面的 /CACHE/images/ 这样的路径也可以定制。

按照这样的逻辑,使用imagekit的话就不需要再定义一个数据库字段来存放,只需要根据原图路径加上这个规则,就能取到对应的图片。

如果所有项目都用imagekit还好,默认的生成规则就行,但是如果其他项目需要用到你这个数据库中的内容,单独提供接口,并且不是使用Django甚至也不是Python开发,那这种逻辑就很复杂了。这种根据参数进行pickle,然后计算md5值的逻辑在其他项目中根本无法使用,因为其他项目没有你的这个Model定义。

基于此情景,需要自定义路径,也就是imagekit中的 namer 。自定义的逻辑很简单,只需要在Django中设置IMAGEKIT_SPEC_CACHEFILE_NAMER使用你自定义的方法,自定义的逻辑可以是这样, 简单copy并修改默认的source_name_as_path的代码即可:

代码语言:javascript
复制
def spec_namer(generator):
    try:
        width = generator.processors[0].width
        height = generator.processors[0].height
        quality = generator.options.get('quality', 'default')
        filename = '%s_%s_s' % (width, height, quality)
    except (IndexError, AttributeError):
        return source_name_as_path(generator)

    source_filename = getattr(generator.source, 'name', None)

    if source_filename is None or os.path.isabs(source_filename):
        # Generally, we put the file right in the cache file directory.
        dir = settings.IMAGEKIT_CACHEFILE_DIR
    else:
        # For source files with relative names (like Django media files),
        # use the source's name to create the new filename.
        dir = os.path.join(settings.IMAGEKIT_CACHEFILE_DIR,
                        os.path.splitext(source_filename)[0])

    ext = suggest_extension(source_filename or '', generator.format)

    return os.path.normpath(os.path.join(dir, '%s%s' % (filename, ext)))

这样就可以了,生成规则就是: CACHE/images/ + 原图路径 + 宽_高_质量 + .jpg 。 注意,设置format为JPEG,后缀就是jpg。

imagekit就简单介绍到这里,功能还有很多,比如水印,去边框等等。如果有这类的使用场景,不妨试试:

http://django-imagekit.readthedocs.org/en/latest/index.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014-09-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档