Django Storages S3 获取每个查询中的所有图像

问题描述 投票:0回答:2

我将我的项目设置为使用带有 S3Boto 后端的 django-storages 的 amazon S3。我的一些模型有 ImageFields 已上传到 S3,并且工作正常。

当我尝试使用 all() 或 filter() 执行查询集时,问题就出现了。对于每个请求,包括 django-admin 请求,django 都会从服务器获取查询集中的每个图像。

我所做的唯一更改是向 ImageField 添加 width_fieldheight_field 以保存高度和宽度,这样我就不必从 S3 检索图像来获取此信息。

如果有人知道为什么会发生这种情况或者如何调试它,那将非常有帮助。我一直在查看 S3Boto 的代码,但不知道要检查什么。

django amazon-s3 boto
2个回答
0
投票

这些对图像文件的访问可能源自

django.db.models.fields.files.ImageField.update_dimension_fields

这是它的描述:

"""
Updates field's width and height fields, if defined.

This method is hooked up to model's post_init signal to update
dimensions after instantiating a model instance.  However, dimensions
won't be updated if the dimensions fields are already populated.  This
avoids unnecessary recalculation when loading an object from the
database.

Dimensions can be forced to update with force=True, which is how
ImageFileDescriptor.__set__ calls this method.
"""    

在您的情况下,我会做的是使用我们自己的 width_field 和 height_field 并在图像上传时仅更新它们一次。以下是我的实现方式(尚未在 S3 的生产环境中进行测试,但可使用本地存储):

class ImageCovered(models.Model):
    def __init__(self, *args, **kwargs):
        # read and store original image data
        super(ImageCovered, self).__init__(*args, **kwargs)
        self.__original_cover_image = self.cover_image

    cover_image = models.ImageField(upload_to=get_upload_path, max_length=200, null=True, blank=True,)
    # We should not use ImageField's width_field nor height_field here, since it might call S3 files.
    # Instead, we implement our own fields and update it once only upon image saving.
    cover_image_height = models.PositiveSmallIntegerField(default=0)
    cover_image_width = models.PositiveSmallIntegerField(default=0)

    def save(self):
        super(ImageCovered, self).save()
        # Check if cover_image has been changed
        if self.__original_cover_image != self.cover_image :
            self.cover_image_height = self.cover_image.height
            self.cover_image_width = self.cover_image.width
            self.__original_cover_image = self.cover_image #replace original data
            super(ImageCovered, self).save(update_fields=('cover_image_height', 'cover_image_width',))

0
投票

我所做的唯一更改是将 width_field 和 height_field 添加到 ImageField 以保存高度和宽度,这样我就不必从 S3 检索图像来获取此信息。

晚了 10 年,但对于在此更改之前上传的任何文件,您可能需要在所有对象上调用相关模型的 save() 方法。

© www.soinside.com 2019 - 2024. All rights reserved.