Django模型中手动触发图片保存方法

Manually trigger image save method in Django model

我有一个带有自定义图像字段的 Django 模型。图像字段在上传时创建一些缩略图大小。代码可能如下所示:

from django.db import models
from utils import CustomImageField

class Photo(models.Model):
    image = CustomImageField()

现在我修改原始图像,假设我旋转了它。现在我想再次触发图像字段的保存方法,以覆盖缩略图并创建旋转版本。因此,我不需要在我的代码中的其他地方旋转缩略图 (DRY)。

有什么想法吗?符合这些思路 - 但究竟如何?

p = Photo.objects.get(pk=1)
p.image.save(...)

我可以完全控制 CustomImageField 小部件。 save() 方法定义为:

def save(self, name, path, save=True):

问题是,方法参数使用什么?

一个选项是手动检查脏字段(请参阅此 SO question) or using a pypi package

或者,如果您想节省内存,可以从字段的 属性 setter 触发调整大小(假设您继承自 FileField

class CustomImageField(FileField):

    def _set_file(self, file):
        has_file_changed = file != self._file
        super(CustomImageField, self)._set_file(file)
        if has_file_changed:
             self.handle_resizing_etc()

    # need to redeclare property so it points to the right _set_file
    file = property(FileField._get_file, _set_file, FileField._del_file)

免责声明:我没有在生产代码中使用过这种方法,在发布此答案之前我也没有编写概念证明,因此它可能无法按预期工作

这个问题看起来像 Programmatically saving image to Django ImageField

的重复

ImageField.save()方法的参数为FileField.save()(其中ImageField是一个子类)记录: https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.fields.files.FieldFile.save

Takes two required arguments: name which is the name of the file, and content which is an object containing the file’s contents. The optional save argument controls whether or not the model instance is saved after the file associated with this field has been altered. Defaults to True.


以下是对我们有效的方法:

class CustomImage(models.Model):
    image = models.ImageField(upload_to=get_file_path, max_length=500)
    orig_name = models.TextField()

这是从 http 资源向 ImageField 添加图像文件的方法:

from django.core.files.base import ContentFile

def download_photo(amazon_id, url):
    img_data = requests.get(url)
    img = CustomImage(orig_name=img_data.url)
    img.image.save(slugify(img.orig_name), ContentFile(img_data.content), save=True)

它也可以在没有 ContentFile 的情况下工作:

new_img = File(open(different_obj.image.path), 'r')
img.image.save(different_obj.image.url, new_img, save=True)

另请参阅: - https://docs.djangoproject.com/en/1.9/topics/files/ - https://djangosnippets.org/snippets/2587/