Reputation: 1108
I can have a property like so in the view class:
class MyExampleView(ModelView):
@property
def can_edit(self):
# Return True or False based on some conditional logic
How can I access the row's attribute so I can for example conditionally show the edit column in the table, maybe if the row's is_active
property is True or False.
Upvotes: 5
Views: 1927
Reputation: 3257
You can make it with some template actions enhancements where you add a method to check row availability:
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
Then you need to override list_row_actions
block in list.html
template to use this new method:
{% 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 %}
And then you need your model class to use the overridden row actions and list template:
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(),
)
Note that original get_list_row_actions
method uses can_view_details
, can_edit
, can_delete
, details_modal
and edit_modal
attributes to define the list of used actions. You discard this logic by overriding it.
Also it does not prevent user from actually editing or deleting objects (e.g. by manually typing the edit view URL in the browser). You need to implement access rights checking in the views methods for example:
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()
Upvotes: 5