使用现有行信息预先填充flask admin create表单

使用现有行信息预先填充flask admin create表单,flask,jinja2,flask-wtforms,flask-admin,Flask,Jinja2,Flask Wtforms,Flask Admin,我正在创建一个新的“复制”操作 我在模型中添加了额外的行操作: column_extra_row_actions = [LinkRowAction('glyphicon glyphicon-duplicate', 'new/')] 我不确定这是否是正确的方法,但我的理由是链接到一个新的创建表单,并用单击复制操作所在行的值预填充这些值。 从这里出发去哪里?我是否重写create\u form()方法?我不想影响创建功能,只需添加一个新的复制功能。以下是我所做的,到目前为止它仍然有效,但我不确定最

我正在创建一个新的“复制”操作

我在模型中添加了额外的行操作:

column_extra_row_actions = [LinkRowAction('glyphicon glyphicon-duplicate', 'new/')]
我不确定这是否是正确的方法,但我的理由是链接到一个新的创建表单,并用单击复制操作所在行的值预填充这些值。
从这里出发去哪里?我是否重写
create\u form()
方法?我不想影响创建功能,只需添加一个新的复制功能。

以下是我所做的,到目前为止它仍然有效,但我不确定最好的方法是:

添加额外模板链接行操作:

column_extra_row_actions = [TemplateLinkRowAction('row_actions.duplicate_row',gettext('Duplicate Record'))]
在ModelView中,我基于创建和编辑方法定义了一个重复的_视图

@expose('/duplicate/',methods=('GET','POST'))
def duplicate_view(self):
    return_url = get_redirect_target() or self.get_url('.index_view')

    if not self.can_create:
        return redirect(return_url)

    id = get_mdict_item_or_list(request.args, 'id')
    if id is None:
        return redirect(return_url)

    old_model = self.get_one(id)

    if old_model is None:
        flash(gettext('Record does not exist.'), 'error')
        return redirect(return_url)

    form = self.edit_form(obj=old_model)
    if not hasattr(form, '_validated_ruleset') or not form._validated_ruleset:
        self._validate_form_instance(ruleset=self._form_edit_rules, form=form)

    if self.validate_form(form):
        new_model = self.create_model(form)
        if new_model:
            flash(gettext('Record was successfully created'),'success')
            if '_add_another' in request.form:
                return redirect(request.url)
            elif '_continue_editing' in request.form:
                # if we have a valid model, try to go to the edit view
                if new_model is not True:
                    url = self.get_url('.edit_view', id=self.get_pk_value(new_model), url=return_url)
                else:
                    url = return_url
                return redirect(url)
            else:
                # save button
                return redirect(self.get_save_return_url(new_model, is_created=True))

    template = 'admin/model/duplicate.html'


    form_opts = FormOpts(widget_args=self.form_widget_args,
                         form_rules=self._form_edit_rules)
    return self.render(template,
                        form=form,
                        form_opts=form_opts,
                        return_url=return_url)
然后在templates/admin/model/row_actions.html中添加新的操作模板(图标):

<!--> DUPLICATE ACTION </!-->
{% macro duplicate_row(action, row_id, row) %}
  {{ link(action, get_url('.duplicate_view', id=row_id, url=return_url), 'fa fa-duplicate glyphicon glyphicon-duplicate') }}
{% endmacro %}

{% macro duplicate_row_popup(action, row_id, row) %}
  {{ lib.add_modal_button(url=get_url('.duplicate_view', id=row_id, url=return_url, modal=True), title=action.title, content='<span class="fa fa-duplicate glyphicon glyphicon-duplicate"></span>') }}
{% endmacro %}
重复操作
{%macro replicate_row(操作,row_id,row)%}
{{link(action,get_url('.duplicate_view',id=row_id,url=return_url),'fa fa duplicate glypicon glypicon duplicate')}
{%endmacro%}
{%macro duplicate_row_弹出窗口(操作,行id,行)%}
{{lib.add_modal_按钮(url=get_url('.duplicate_view',id=row_id,url=return_url,modal=True),title=action.title,content='')}
{%endmacro%}
最后创建从create in templates/admin/model/duplicate.html继承的重复页面模板:

{% extends 'admin/model/create.html' %}
{% block body %}
  <h1> Duplicate  View</h1>
  {{super()}}
{% endblock %}
{%extends'admin/model/create.html%}
{%block body%}
重复视图
{{super()}}
{%endblock%}

我建立在@Nidhal Selmi的基础上,下面的内容很好地帮助我在Flask Admin中复制当前行/记录:

首先,我使用的导入:

from flask_admin import AdminIndexView, expose
from flask_admin.contrib.sqla import ModelView
from flask_admin.model.template import LinkRowAction
from flask_admin.helpers import get_redirect_target, flash_errors
from flask_admin.model.helpers import get_mdict_item_or_list
from flask import abort, current_app, flash, redirect, request, url_for
from gettext import gettext
接下来,我的默认模型视图类,带有/duplicate/view

注意我是如何使用Flask Admin的内置
列\额外\行\操作的

class MyModelView(ModelView):
    """Customized model view for Flask-Admin page (for database tables)"""

    column_extra_row_actions=[
        LinkRowAction(
            icon_class='glyphicon glyphicon-duplicate',
            # Calls the .../duplicate?id={row_id} view
            # with the row_id from the Jinja template
            url='duplicate?id={row_id}',
            title="Duplicate Row"
        ),
    ]

    @expose('/duplicate/')
    def duplicate_record(self):
        """Make a duplicate of the current record"""

        # Grab parameters from URL
        view_args = self._get_list_extra_args()

        # Duplicate current record
        return_url = get_redirect_target() or self.get_url('.index_view')

        if not self.can_create:
            return redirect(return_url)

        id_ = get_mdict_item_or_list(request.args, 'id')
        if id_ is None:
            flash(gettext("Can't find the 'id' for the record to be duplicated."), 'error')
            return redirect(return_url)

        old_model = self.get_one(id_)
        if old_model is None:
            flash(gettext('Record does not exist.'), 'error')
            return redirect(return_url)

        # Make a clone of the old model, without the primary key
        dont_copy_cols = ('unique_name_column',)
        new_model = clone_model(old_model, dont_copy_cols=dont_copy_cols)

        # Add duplicate record to the database
        db.session.add(new_model)
        db.session.commit()
        flash(gettext("You have successfully duplicated that record."), 'success')

        return redirect(return_url)

下面是我在上面使用的一个函数,用于克隆记录,删除主键,并用稍后要替换的随机数替换某些列数据(对于必须唯一的列):


由于“复制”是编辑和创建操作的混合,我是否应该使用
TemplateLinkRowAction()
。它破坏了表单验证。您找到合适的工作解决方案了吗?您提到此解决方案不起作用。你对此有任何迭代吗?好消息是我找到了一个解决方案。据我记忆所及,模型被覆盖/未正确CPI时出现问题。这就是我能说的,对不起,已经有一段时间了,我的工作代码不是公开的。没问题。你有什么建议,如何修复上面的代码以便我可以使用它?我建议在他们的github上打开一个问题:或者实现我的代码并尝试破坏/调试它(找到问题),我花了几天时间。祝你好运!
def clone_model(model, dont_copy_cols=None, **kwargs):
    """Clone an arbitrary SQLAlchemy model object without its primary key values"""

    # Ensure the model's data is loaded before copying
    model.id
    table = model.__table__

    non_pk_columns = [k for k in table.columns.keys() if k not in table.primary_key]
    data = {c: getattr(model, c) for c in non_pk_columns}
    data.update(kwargs)

    if dont_copy_cols is None:
        dont_copy_cols = []

    # Check if column is either a primary_key or has a unique constraint
    dont_copy_cols2 = [c.name for c in table.columns if any((c.primary_key, c.unique))]

    # If this column must be unique, use a random number,
    # which will be replaced manually
    for c in non_pk_columns:
        if c in dont_copy_cols or c in dont_copy_cols2:
            # Most of these columns can't be null
            data[c] = random.randint(1_000_000_000, 9_999_999_999)

    clone = model.__class__(**data)

    return clone