通过递归调用模型生成用户提交的图像的缩略图

时间:2012-05-27 09:05:46

标签: django django-models

我正在通过tutorial了解如何加载图片,我完全失去了这个人用来为提交的图片生成缩略图的方法

这是他的代码的缩减:

import os.path
from PIL import Image as PImage
from settings import MEDIA_ROOT
from tempfile import *

class Image(models.Model):
    image = models.FileField(upload_to="images/")
    thumbnail = models.ImageField(upload_to="images/", blank=True, null=True)

    def save(self, *args, **kwargs):
        super(Image, self).save(*args, **kwargs)
        im = PImage.open(pjoin(MEDIA_ROOT, self.image.name))

        fn, ext = os.path.splitext(self.image.name)
        im.thumbnail((128,128), PImage.ANTIALIAS)
        thumb_fn = fn + "-thumb" + ext
        tf = NamedTemporaryFile()
        im.save(tf.name, "JPEG")
        self.thumbnail.save(thumb_fn, File(open(tf.name)), save=False)
        tf.close()

        super(Image, self).save(*args, ** kwargs)

所以我对此的具体问题是:

  1. 他使用FileField作为图像和ImageField作为缩略图的原因是什么?
  2. 根据我的理解,super(Image, self).save(*args, **kwargs)会保存模型。但他为什么最后再打电话呢?
  3. 然后我真的不明白NamedTemporaryFile()扮演的角色以及调用self.thumbnail.save(thumb_fn, File(open(tf.name)), save=False)时究竟发生了什么

1 个答案:

答案 0 :(得分:2)

  1. 我也会将ImageField用于主图像。的ImageField 继承自FileField,但确保只有图像文件 上传,除其他外: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ImageField

  2. 首先save()将图像对象保存到数据库,但它(假设)还没有设置缩略图。第二次save()调用使用对实例所做的更改(添加缩略图)更新数据库。     

    他用缩略图字段设置 self.thumbnail.save(thumb_fn, File(open(tf.name)), save=False), 但这只会将缩略图保存到适当位置的文件中,并使用其路径填充实例的thumbnail attr。然后,您需要再次在Image实例上调用save()以将对象上的更改更新为DB(添加缩略图)。

  3. 代码正在读取上传的主图像文件,并且该图像在内存中组成了缩略图(在内存中,它还不作为文件存在)。

    但是这个缩略图需要保存在一个文件中,以便它可以与Django ImageFile一起使用(期望上传的文件暂时保存在磁盘上),这就是他正在做的事情{ {1}}。

    NamedTemporaryFile实例需要将该文件复制到适当的位置(使用ImageFile设置+ MEDIA_ROOT参数设置)。