Hiding fields in Flask-Admin depending on logged in user?
Asked Answered
S

1

6

I have Users and Roles in my Flask app thanks to Flask-Security.

For some roles I would like to hide certain fields in the forms created by Flask-Admin.

I know about customizing ModelViews with eg. form_create_rules = ('title', 'file') but while instantiating a ModelView there isn't access to the current request so current_user.has_role(USER_ROLE) can't be called.

Is there any other way to achieve this?

Slash answered 30/5, 2016 at 20:5 Comment(3)
Are you sure you cannot access the request while instantiating a ModelView? Anyway, here is an example github.com/sasaporta/flask-security-admin-example/blob/master/…Glass
Yes, current_user is not available then. It's only available in is_accessible() and _handle_view() (like they do in the example). But setting self.form_create_rules in those methods has no effect :( .Slash
You can change self.form_create_rules and regenerate forms, but it is discouraged - forms are cached for performance reasons. Instead, you can override create_form and edit_form and return different forms (or remove fields from existing form). See here: github.com/flask-admin/flask-admin/blob/master/flask_admin/…Moire
G
10

One way of achieving this is to create multiple view classes and register these view classes against their appropriate roles. See this answer on how to register roles to views. Using view inheritance you can keep common functionality in the "base" class.

For example, suppose we have a user table that implements the Flask-Security mixin and we want the role "admin" to be able to read/set the active field and anyone with the role "user" not to see this field. The class AdminView is defined in the referenced answer.

class AdminUserView(AdminView):

    column_list = ['first_name', 'last_name', 'email', 'roles', 'active']

    form_columns = ['first_name', 'last_name', 'email', 'active', 'roles']

    # Other common functionality here

class UserView(AdminUserView): 

    # Just redefine the columns that can be seen/edited

    column_list = ['first_name', 'last_name', 'email', 'roles']

    form_columns = ['first_name', 'last_name', 'email', 'roles']

# register your views and remember to set a unique endpoint as we are using the same model in multiple views

admin.add_view(AdminUserView(model=User, session=db.session, category="Accounts", name="Users", endpoint="users_admin", roles_accepted=["admin"]))
admin.add_view(UserView(model=User, session=db.session, category="Accounts", name="Users", endpoint="users_user", roles_accepted=["user"]))
Gruver answered 31/5, 2016 at 19:21 Comment(1)
can not add roles_accepted TypeError: __init__() got an unexpected keyword argument 'roles_accepted'Clinician

© 2022 - 2024 — McMap. All rights reserved.