flask-admin - 如何将ImageUploadField与pymongo后端一起使用

时间:2014-05-14 23:11:13

标签: python flask-admin

我使用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应该将图像保存在uploads目录中,并在模型中用文件名替换二进制对象。这种情况发生在sqla而不是pymongo。看起来好像什么都没有调用ImageUploadField类的populate_obj方法。

知道我有什么不妥之处吗?

1 个答案:

答案 0 :(得分:2)

得到了它。 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

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

form.photo.populate_obj(model, 'photo')
如果已上传照片,则会明确执行

注意:我还没有使用InLineFieldList测试修复,照片现在是一个ImageUploadField。