有条件地允许在 Flask 管理 ModelView 的列表视图中进行编辑

use*_*973 5 edit flask flask-admin

我可以在视图类中拥有这样的属性:

class MyExampleView(ModelView):

    @property
    def can_edit(self):
        # Return True or False based on some conditional logic
Run Code Online (Sandbox Code Playgroud)

我如何访问该行的属性,以便我可以有条件地显示表中的编辑列,也许该行的is_active属性是 True 或 False。

Ser*_*bin 5

您可以通过一些模板操作增强来实现,其中添加一个方法来检查行可用性:

from flask_admin.model import template

class AccessMixin:
    def has_access(self, row):
        raise NotImplementedError()

class ViewRowAction(template.ViewRowAction, AccessMixin):
    def has_access(self, row):
        return True

class EditRowAction(template.EditRowAction, AccessMixin):
    def has_access(self, row):
        return row.is_active

class DeleteRowAction(template.DeleteRowAction, AccessMixin):
    def has_access(self, row):
        return row.is_active
Run Code Online (Sandbox Code Playgroud)

然后你需要重写模板list_row_actions中的块list.html才能使用这个新方法:

{% extends 'admin/model/list.html' %}

{% block list_row_actions scoped %}
  {% for action in list_row_actions %}
    {% if action.has_access(row) %}
      {{ action.render_ctx(get_pk_value(row), row) }}
    {% endif %}
  {% endfor %}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

然后您需要模型类使用覆盖的行操作和列表模板:

from flask_admin.contrib.sqla.view import ModelView

class MyExampleView(ModelView):
    list_template = 'app_list.html'

    def get_list_row_actions(self):
        return (
            ViewRowAction(),
            EditRowAction(),
            DeleteRowAction(),
        )
Run Code Online (Sandbox Code Playgroud)

请注意,原始get_list_row_actions方法使用can_view_detailscan_editcan_delete和属性来定义所用操作的列表。您可以通过覆盖该逻辑来丢弃它。details_modaledit_modal

此外,它不会阻止用户实际编辑或删除对象(例如,通过在浏览器中手动键入编辑视图 URL)。您需要在视图方法中实现访问权限检查,例如:

from flask import flash, redirect, request
from flask_admin import expose
from flask_admin.babel import gettext
from flask_admin.helpers import get_redirect_target
from flask_admin.model.helpers import get_mdict_item_or_list

class MyExampleView(ModelView):
    @expose('/edit/', methods=('GET', 'POST'))
    def edit_view(self):
        """This code was copied from the
           flask_admin.model.base.BaseModelView.edit_view method"""
        return_url = get_redirect_target() or self.get_url('.index_view')

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

        model = self.get_one(id)

        if model is None or not model.is_active:
            flash(gettext('Record does not exist or you have 
                          not enough access rights.'), 'error')
            return redirect(return_url)

        return super(MyExampleView, self).edit_view()
Run Code Online (Sandbox Code Playgroud)