我在模型中添加了额外的行操作:
column_extra_row_actions = [LinkRowAction('glyphicon glyphicon-duplicate', 'new/')]
我不确定这是否是正确的处理方法,但我的理由是链接到新的创建表单,并用单击重复操作的行的值预填充值。
从这里开始?如何重写create_form()
方法?我不想影响创建功能,只需添加一个新的副本即可。
答案 0 :(得分:1)
我建立在@Nidhal Selmi 的 code 之上,以下内容非常适合我在 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/ 视图。
注意我如何使用 Flask-Admin 的内置 column_extra_row_actions
。
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)
这是我上面使用的一个函数,用于克隆记录,删除主键,并用随机数替换某些列数据,以便稍后替换(对于必须唯一的列):
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
答案 1 :(得分:0)
这就是我所做的,到目前为止,它仍然有效,但是我不确定最好的方法:
添加额外的“模板链接行”操作:
column_extra_row_actions = [TemplateLinkRowAction('row_actions.duplicate_row',gettext('Duplicate Record'))]
在ModelView中,我基于创建和编辑方法定义了repeat_view
@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)
然后将新的操作模板(icon)添加到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 %}
最后创建重复页面模板,该模板继承自template / admin / model / duplicate.html中的create:
{% extends 'admin/model/create.html' %}
{% block body %}
<h1> Duplicate View</h1>
{{super()}}
{% endblock %}