带表单的Flask-Admin批处理操作

时间:2016-03-07 19:26:25

标签: python flask flask-admin

我有一个Flask应用Flask-SQLAlchemyFlask-Admin

我想执行批处理操作,但是使用表单。例如,我想为表单属性设置相同的文本值,但该值由用户输入。

我看到documentation for batch actions,但它只有预定义数据的示例。

是否可能,或者可能有一些解决方法?

1 个答案:

答案 0 :(得分:3)

我实现这一目标的方法是在@action方法中执行内部POST。

class AddressView(AdminView):

    # ... ....

    @action('merge', 'Merge', 'Are you sure you want to merge selected addresses?')
    def action_merge(self, ids):

        if len(ids) < 2:
            flash("Two or more addresses need to be selected before merging")
            return

        return_url = request.referrer
        return redirect(url_for('mergeaddresses.index', return_url=return_url), code=307)   

然后定义两个路由,一个用于内部帖子,然后一个用于从接收用户输入数据的表单接收提交POST(在下面的情况下为MergeAddressForm)。

在下面的示例中,我碰巧使用Flask-Admin BaseView来处理路由。请注意如何检索flask-admin列表视图中的原始已检查ID,然后将其作为编码的逗号分隔列表隐藏字段存储在表单中,同样将return_url存储回到flask-admin列表视图中。

class MergeAddressesView(BaseView):

    form_base_class = BaseForm

    def __init__(self, name=None, category=None,
                 endpoint=None, url=None,
                 template='admin/index.html',
                 menu_class_name=None,
                 menu_icon_type=None,
                 menu_icon_value=None):
        super(MergeAddressesView, self).__init__(name,
                                             category,
                                             endpoint,
                                             url or '/admin',
                                             'static',
                                             menu_class_name=menu_class_name,
                                             menu_icon_type=menu_icon_type,
                                             menu_icon_value=menu_icon_value)
        self._template = template

    def is_visible(self):
        return False

    @expose('/', methods=['POST'])
    def index(self):
        if request.method == 'POST':
            # get the original checked id's
            ids = request.form.getlist('rowid')

            merge_form = MergeAddressForm()
            merge_form.process()
            joined_ids = ','.join(ids)
            encoded = base64.b64encode(joined_ids)
            merge_form.ids.data = encoded
            _return_url = request.args['return_url']
            merge_form.return_url.data = _return_url
            self._template_args['form'] = merge_form
            self._template_args['cancel_url'] = _return_url
            return self.render(self._template)

    @expose('/merge', methods=['POST'])
    def merge(self):

        if request.method == 'POST':
            merge_form = MergeAddressForm(selection_choices=[])
            decoded = base64.b64decode(merge_form.ids.data)
            ids = decoded.split(',')
            # do the merging
            address_merger = AddressMerger(ids=ids, primary_id=merge_form.primary_address.data)
            address_merger.merge()
            # return to the original flask-admin list view
            return redirect(merge_form.return_url.data)

我的用户输入表单模板如下所示。请注意操作网址。

{% extends 'admin/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}

{% block body %}
    <h3>{{ admin_view.name|title }}</h3>
    <form role="form" action="{{ url_for('mergeaddresses.merge') }}" method="post" name="form">

        {{ form.hidden_tag() }}

        {{ wtf.form_errors(form) }}

        {{ wtf.form_field(form.primary_address) }}

        <button type="submit" class="btn btn-primary">Merge</button>
        <a href="{{ cancel_url }}" class="btn btn-danger" role="button">Cancel</a>
    </form>
{% endblock %}