使用flask-admin,我如何获得支持不存在标签的标签字段?

时间:2013-05-01 13:42:59

标签: python flask

我有两个模型Product和Tag,并在SQLAlchemy中设置了多对多的关系。 使用它作为烧瓶管理员示例显示:

 admin.add_view(ProductAdmin(db.session))

我获得了一个创建表单,并且只能选择现有标签。 我知道flask-admin正在使用select2,而select2有一种添加新标签的风格。 我在flask-admin文件夹下的Form.py中找到了Slect2TagsField类。

那么,如何通过使用flask-admin来获取支持在我的产品创建表单中添加新标记的标记字段?

提前致谢。

2 个答案:

答案 0 :(得分:2)

不幸的是,Flask-Admin没有公开任何AJAX端点,因此无法在Select2字段中创建新模型。

然而,有办法让它发挥作用:

  1. 从管理表单中排除标记字段
  2. 将新的Select2TagsField贡献给具有不同名称的表单(因此没有名称冲突)
  3. 在显示新/编辑视图之前,将标记列表序列化为字符串数组并为Select2TagsField做出贡献
  4. 在提交模型(on_model_change)之前,查看列表,执行数据库查找以查找现有标记并为缺失标记创建模型
  5. 将标签模型列表提供给模型

答案 1 :(得分:1)

您可以创建自己的TagField并将其添加到ModelView.您必须覆盖某些字段功能。

我整理了使用select2版本4的demo application并且比这个答案更详细。

标记字段:

class CustomTagField(Select2TagsField):

    widget = CustomTagWidget(multiple=True)

    def pre_validate(self, form):
        pass

    def process_formdata(self, valuelist):
        if valuelist:
            self.data = []
            for tagname in valuelist:
                rv = Tag.query.filter_by(name=tagname).first()
                if rv:
                    self.data.append(rv)
                else:
                    self.data.append(Tag(name=tagname))
        else:
            self.data = []

    def iter_choices(self):

        self.blank_text = ""

        tags = list(set([str(tag.name) for tag in Tag.query.all()]))
        model_tags = [tag.name for tag in self.object_data]

        self.choices = [[tag, tag] for tag in tags]

        # Yield empty object in order to have an empty placeholder
        yield (u'__None', self.blank_text, self.data is None)

        for value, label in self.choices:
            yield (value, label, value in model_tags)

自定义窗口小部件:(类似于Select2TagsWidget,但未设置data-role,因此form.js不会使其成为常规的select2字段)

class CustomTagWidget(widgets.Select):
    def __call__(self, field, **kwargs):
        kwargs.setdefault('data-tags', '1')
        # Or call select2 in tags mode

        allow_blank = getattr(field, 'allow_blank', False)
        if allow_blank and not self.multiple:
            kwargs['data-allow-blank'] = u'1'

        return super(CustomTagWidget, self).__call__(field, **kwargs)

在您的管理员中:

form_extra_fields = {
        'tags': CustomTagField(
            'Tags',
        ),
}

然后覆盖您的管理模板,在您的字段上以标记模式调用select2(admin/js/form.js也会尝试设置该字段的样式):

$('#tags').select2({
  tags: true,
});