How to make a field non-editable in Flask Admin view of a model class
Asked Answered
T

3

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.

Teets answered 12/2, 2014 at 11:48 Comment(0)
T
24

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:

Turves answered 23/3, 2014 at 20:42 Comment(7)
This however also marks "name" as disabled in the creation form. Is there any way to only disable a field in the edit form?Furness
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.Bernoulli
@blurrcat, I had the same question. Below is the solution I came up with.Opsonize
Is it possible somehow to make field disabled for 'Edit' form but enabled for 'Create' form?Rape
'readonly' only works for text fields. 'disabled' will clear all values ( even relationships) !Koralie
Is it possible to clear readonly field ? in some case ? as it is on image upload field (it has clear button)Abate
if user inspect the page and removed the read-only or disabled he will able to change the input valueLumpish
O
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
    ]
Opsonize answered 8/8, 2016 at 16:57 Comment(3)
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?Rape
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 :)Opsonize
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').Rape
R
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.

Rape answered 3/5, 2017 at 16:54 Comment(1)
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 :DRape

© 2022 - 2024 — McMap. All rights reserved.