12

I have a User model class and password is one attribute among many. I am using Flask web framework and Flask-Admin extension to create the admin view of my model classes. I want to make certain fields in the admin view like password non editable or not show them at all. How do I do it?

I can make the fields not show up in the normal view but when I click on the edit button of any record in the table, all fields show up and are editable.

ajay
  • 9,402
  • 8
  • 44
  • 71

3 Answers3

23

You should extend your view from ModelView and overwrite the necessary fields.

In my class it looks like this:

class UserView(ModelView):

    column_list = ('first_name', 'last_name', 'username', 'email')
    searchable_columns = ('username', 'email')
# this is to exclude the password field from list_view:
    excluded_list_columns = ['password']
    can_create = True
    can_delete = False
# If you want to make them not editable in form view: use this piece:
    form_widget_args = {
        'name': {
            'readonly': True
        },
    }

Hope this helps! For more information check out the documentation:

Remo L.
  • 720
  • 6
  • 19
  • 3
    This however also marks "name" as disabled in the creation form. Is there any way to only disable a field in the edit form? – blurrcat Sep 05 '15 at 03:55
  • You might want to use the `readonly` attribute instead of `disabled`. The latter causes the field to be excluded from the submitted form data, which may result in the field getting set to None/null depending on what backend you're using. – booshong Sep 28 '15 at 13:41
  • @blurrcat, I had the same question. Below is the solution I came up with. – Phillip Martin Aug 08 '16 at 16:57
  • 3
    Is it possible somehow to make field disabled for 'Edit' form but enabled for 'Create' form? – tm- Oct 18 '16 at 17:48
  • 3
    'readonly' only works for text fields. 'disabled' will clear all values ( even relationships) ! – David Lin Feb 20 '17 at 05:58
  • Is it possible to clear readonly field ? in some case ? as it is on image upload field (it has clear button) – Beqa Bukhradze Jun 07 '18 at 06:44
  • if user inspect the page and removed the read-only or disabled he will able to change the input value – Mahmoud Magdy Dec 13 '21 at 19:35
7

Here is a solution that expands upon Remo's answer and this so answer. It allows for different field_args for edit and create forms.

Custom Field Rule Class

from flask_admin.form.rules import Field

class CustomizableField(Field):
    def __init__(self, field_name, render_field='lib.render_field', field_args={}):
        super(CustomizableField, self).__init__(field_name, render_field)
        self.extra_field_args = field_args

    def __call__(self, form, form_opts=None, field_args={}):
        field_args.update(self.extra_field_args)
        return super(CustomizableField, self).__call__(form, form_opts, field_args)

UserView Class

class UserView(ModelView):

    column_list = ('first_name', 'last_name', 'username', 'email')
    searchable_columns = ('username', 'email')

    # this is to exclude the password field from list_view:
    excluded_list_columns = ['password']
    can_create = True
    can_delete = False

    # If you want to make them not editable in form view: use this piece:
    form_edit_rules = [
        CustomizableField('name', field_args={
            'readonly': True
        }),
        # ... place other rules here
    ]
Community
  • 1
  • 1
Phillip Martin
  • 1,910
  • 15
  • 30
  • 2
    Great hack! But meantime it hides all the other fields on form. Do I have to set them manuall inside form_edit_rules or there is another, more smooth way? – tm- Oct 18 '16 at 18:02
  • The only way I've found so far is to set them manually in `form_edit_rules`. Perhaps if you find an improvement, you can share it here :) – Phillip Martin Oct 20 '16 at 15:11
  • Quite a high ping for answer... :) So actually, if no special rules for fields are required (as in my case), I finished up with just extending `form_edit_rules` by any columns list like `form_edit_rules.extend(column_list)`. And remove doubled one: `form_edit_rules.remove('name')`. – tm- May 03 '17 at 15:43
7

Yet another way to work the problem around is to use Flask-Admin ModelView method called on_form_prefill to set readonly property argument. According to Flask-Admin Docs:

on_form_prefill(form, id)

Perform additional actions to pre-fill the edit form.

Called from edit_view, if the current action is rendering the form rather than receiving client side input, after default pre-filling has been performed.

In other words, this is a trigger, which is run when opening only Edit form, not the Create one.

So, the solution for the example used above would be:

class UserView(ModelView):
    ...
    def on_form_prefill(self, form, id):
        form.name.render_kw = {'readonly': True}

The method is run after all other rules applied, so none of them are broken, including set of columns.

Community
  • 1
  • 1
tm-
  • 333
  • 1
  • 3
  • 10
  • As readonly property is set inside method, we can apply it only in some certain cases, according to some other fields existing values, for example. That was the reason I had to find it after few months :D – tm- May 03 '17 at 16:58