【问题标题】:flask-admin - how to use ImageUploadField with the pymongo backendflask-admin - 如何将 ImageUploadField 与 pymongo 后端一起使用
【发布时间】:2014-07-03 05:14:36
【问题描述】:

我将 flask-admin 与 pymongo(不是 mongoengine)数据库一起使用,但在使用新的 flask-admin ImageUploadField 时遇到了严重问题。

基本上我就是无法让它工作。在过去的两天里,我一直在尝试复制示例,但没有成功,这些示例在 sqla 上运行良好。这是我的管理类定义:

from jinja2 import Markup
from flask_admin.contrib.pymongo import ModelView, filters
from flask_admin import form
from flask_admin.model import fields
from flask_admin.form.upload import ImageUploadField
from flask_admin.form import rules, widgets
import flask_wtf as wtf
from wtforms import validators as wtfv
from wtforms import widgets as wtfw
from wtforms import fields as wtff


class PhotoForm(wtf.Form):
    label = wtff.TextField('Label')
    file = ImageUploadField('Image', base_path=file_path, thumbnail_size=(100, 100, True))

    def __init__(self, *args, **kwargs):
        kwargs['csrf_enabled'] = True
        super(PhotoForm, self).__init__(*args, **kwargs)


class EquipmentForm(wtf.Form):
    photo = fields.InlineFieldList(fields.InlineFormField(PhotoForm))


class EquipmentViewRoot(ModelView):

    def _list_thumbnail(view, context, model, name):
        if not model['photo']:
            return ''
        return Markup('<img src="%s">' % url_for('static', filename=form.thumbgen_filename(model.path)))

    can_create = True
    column_list = ('photo')
    column_formatters = {
        'photo': _list_thumbnail
    }

    form = EquipmentForm

表单显示正确,但是当我单击保存按钮时,如果选择了图像文件,我会收到错误消息 pymongo 无法保存模型,因为它包含二进制对象。

根据文档(以及源代码),ImageUploadField 应该将图像保存在上传目录中,并在模型中将二进制对象替换为文件名。 sqla 会发生这种情况,而 pymongo 不会。好像没有调用 ImageUploadField 类的 populate_obj 方法。

知道我做错了什么吗?

【问题讨论】:

    标签: python flask-admin


    【解决方案1】:

    知道了。 ImageUploadField 的 populate_obj 方法对 pymongo 后端没有效果,因为它使用对象属性,而 pymongo 使用普通字典而不是对象。

    我通过简单地继承 ImageUploadField 并重载 populate_obj 方法以使用字典来修复它。

    我创建了一个 utils.py 文件,包括以下内容:

    from flask_admin.form.upload import ImageUploadField as iuf
    from werkzeug.datastructures import FileStorage
    
    class ImageUploadField(iuf):
        def __init__(self, *args, **kwargs):
            super(ImageUploadField, self).__init__(*args, **kwargs)
    
        def populate_obj(self, obj, name):
            field = getattr(obj, name, None)
            if field:
                # If field should be deleted, clean it up
                if self._should_delete:
                    self._delete_file(field)
                    setattr(obj, name, None)
                    return
    
            if self.data and isinstance(self.data, FileStorage):
                if field:
                    self._delete_file(field)
    
                filename = self.generate_name(obj, self.data)
                filename = self._save_file(self.data, filename)
                # update filename of FileStorage to our validated name
                self.data.filename = filename
    
                obj[name] = filename  # this is the patched line
    

    然后在管理类中我导入新的子类而不是原来的。 EquipmentViewRoot(ModelView) 类现在重载 on_model_change() 方法,其中以下指令

    form.photo.populate_obj(model, 'photo')
    

    如果已上传照片,则显式执行。

    注意:我尚未使用 InLineFieldList 测试修复,照片现在是单个 ImageUploadField。

    【讨论】:

      猜你喜欢
      • 2016-01-14
      • 2016-01-24
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 2020-04-22
      • 1970-01-01
      相关资源
      最近更新 更多