Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Readonly form field in edit view - Flask-Admin

I tried to set a form field as readonly just for the edit view in a Flask-Admin application. Following the answers to this question I know that if I have this

class MyView(ModelView):
    form_widget_args = {
        'title': {
            'readonly': True
        }
    }

I can set a form field as readonly, but this is applied to both create and edit views. How can I apply an argument to the edit view only?

like image 401
osjerick Avatar asked Jun 28 '18 01:06

osjerick


3 Answers

A pure python solution could be using the on_form_prefill callback function that admin provides, and it's only run in the edit view. You wouldn't need form_widget_args in that case.

You could have something like this to edit the form dynamically, making that field read only:

class MyView(ModelView):
  def on_form_prefill(self, form, id):
    form.title.render_kw = {'readonly': True}
like image 81
Luis Orduz Avatar answered Nov 16 '22 17:11

Luis Orduz


Another way to do it is to use form_edit_rules and form_create_rules. Display the fields you only want in create view, and add the field you want to be displayed in edit view and make it read-only

form_create_rules = (
    'col1', 'col2', 'col3')
form_edit_rules = (
    'col1', 'col2', 'col3', 'col4')

form_widget_args = {
    'col4': {
        'disabled': True
    }
}
like image 27
Novice Avatar answered Nov 16 '22 17:11

Novice


I would do a little workaround for this. Create a custom edit template and add it to your class. The standard edit template you find in the flask repository on github (standard edit template)

class MyView(ModelView):
    edit_template = 'my_custom_edit_template.html'

And in your custom edit template make a javascript function which disables your element. So it's only disabled in edit view and not in the create view.

{% block tail %}
    {{ super() }}
    {{ lib.form_js() }}
    <script>
    window.onload = function () {
        document.getElementById("myfield_id").disabled = true;
    }
    </script>
{% endblock %}

It's maybe not the best solution but it works for me. I think it should also be possible to change the jinja2 template to directly disable the filed. I tried: {{ form.myfield_id(disabled=True) }} but then it renders my field twice... but my first approach works.

like image 3
xFL Avatar answered Nov 16 '22 16:11

xFL