Flask-Admin:显示来自 S3 的图像

Flask-Admin: displaying images from S3

我在 Flask-Admin 中创建了一个自定义 ImageUploadField 用于将图像上传到 S3。它工作得很好,除了当我 select 一条记录时 - img src 标签现在将 /static/ 添加到我所有的文件路径中,我看不到图像。这是 Flask-Admin 生成的标签:

<div class="image-thumbnail"> <img src="/static/https://mybucket.s3.amazonaws.com/mypicture.jpg"> </div><input class="form-control" id="image1" name="image1" type="file"></div>

我还从我的应用程序提供静态文件,因此全局更改 static 目录不是一个好主意。

ImageUploadField 上似乎有几个属性可以根据需要进行修改(endpointurl_relative_pathrelative_pathbase_path)但是我仍然无法修复它。

Flask-Admin 使用 urlparse.urljoin 创建文件名,因此如果 'relative_path' 参数没有尾部斜杠,它可能会在前面添加 '/static'

一点想法,祝你好运!

原来 widget 负责生成 URL。它还在 static 端点中查找图像(因此 endpoint 在初始化 ImageUploadField class 时默认为 static 的原因。为了解决这个问题,我创建了这个小部件的子 class 并修改了 HTML 以直接指向存储在表单中的 S3 URL。

尽管 Flask-Admin 文档中没有深入讨论小部件,但您可以从 source code.

的部分内容中了解它们的工作原理。

下面是小部件的完整代码,以及我自定义的部分代码 ImageUploadField

class S3ImageUploadInput(ImageUploadInput):

    def __call__(self, field, **kwargs):
        kwargs.setdefault('id', field.id)
        kwargs.setdefault('name', field.name)

        args = {
            'file': html_params(type='file',
                                **kwargs),
            'marker': '_%s-delete' % field.name
        }

        if field.data and isinstance(field.data, string_types):
            # calling field.data to directly return S3 URL
            url = field.data
            args['image'] = html_params(src=url)

            template = self.data_template
        else:
            template = self.empty_template

        return HTMLString(template % args)


class S3ImageUploadField(ImageUploadField):

    widget = S3ImageUploadInput()

    def __init__(self, *args, **kwargs):
        super(S3ImageUploadField, self).__init__(*args, **kwargs)

将 "endpoint" 添加到字典 some_image

form_args = dict(
    some_image=dict(
        endpoint=you_url_complete,
        base_path='/some/folder/static',
        relative_path='some_image/',
        url_relative_path='uploads/',
        namegen=your_namegen_func_here,
        storage_type_field='some_image_storage_type',
        bucket_name_field='some_image_storage_bucket_name',
    )
)