【问题标题】:Manually trigger image save method in Django model在Django模型中手动触发图像保存方法
【发布时间】:2016-11-19 16:11:06
【问题描述】:

我有一个带有自定义图像字段的 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):

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

【问题讨论】:

  • 你不能只调用 p.save() 吗?
  • 不,这不会调用图像字段的保存方法。如果是这样,在大多数情况下效率会非常低。
  • 不够通过。您应该发布您的 CustomImageField
  • 你的问题我不清楚。我们是否应该告诉您要传递给您创建的方法的参数以及我们不知道它做什么的参数?谁比你更清楚这一点?能否请您改述一下您的问题?

标签: django image model save field


【解决方案1】:

一个选项是脏字段检查,手动(参见SO question)或使用pypi package

或者,如果您想节省内存,可以从字段的属性设置器触发调整大小(假设您继承自 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)

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

【讨论】:

    【解决方案2】:

    这个问题看起来与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

    接受两个必需的参数:name 是文件的名称,以及 content 是一个包含文件内容的对象。这 可选的 save 参数控制模型实例是否为 在与此字段关联的文件被更改后保存。 默认为 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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 2015-02-24
      • 2014-09-25
      • 2019-03-04
      • 1970-01-01
      • 2011-12-15
      • 2012-02-04
      相关资源
      最近更新 更多