Flask App Builder throws KeyError on arrays

Viewed 413

I have a table with an attribute of type array of string:

create table mytable(
        suffix VARCHAR(200) PRIMARY KEY,
        label VARCHAR(200) NOT NULL,
        sourceuris VARCHAR(200)[],
);

It is defined in models.py as:

class mytable(Model):
    suffix = Column(String(200), primary_key=True)
    label =  Column(String(200), nullable=False)
    sourceuris = Column(ARRAY(String(200)))

    def __repr__(self):
        return self.label

Now I want to define a view on it using Flask AppBuilder in views.py:

class mytable(ModelView):
    datamodel = SQLAInterface(mytable)                                                                                                                                                                                                                                                                       
    label_columns = {'label':'Name'}
    list_columns = ['suffix', 'label', 'sourceuris']

It compiles but when I open the view in the web application at http://127.0.0.1:5000/mytableviewview/list/, then I get a `KeyError: 'sourceuris':

2020-08-26 12:50:42,329:WARNING:flask_appbuilder.models.filters:Filter type not supported for column: sourceuris
2020-08-26 12:50:42,329:WARNING:flask_appbuilder.models.filters:Filter type not supported for column: sourceuris
2020-08-26 12:50:42,332:WARNING:flask_appbuilder.models.filters:Filter type not supported for column: sourceuris
2020-08-26 12:50:42,394:ERROR:app:Exception on /mytableview/list/ [GET]
Traceback (most recent call last):
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/security/decorators.py", line 109, in wraps
    return f(self, *args, **kwargs)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/views.py", line 552, in list
    return self.render_template(
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/baseviews.py", line 280, in render_template
    return render_template(
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/templating.py", line 137, in render_template
    return _render(
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask/templating.py", line 120, in _render
    rv = template.render(context)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/general/model/list.html", line 2, in top-level template code
    {% import 'appbuilder/general/lib.html' as lib %}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/base.html", line 1, in top-level template code
    {% extends base_template %}
  File "/home/konrad/projekte/hito/database-frontend/app/templates/base.html", line 1, in top-level template code
    {% extends 'appbuilder/baselayout.html' %}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/baselayout.html", line 2, in top-level template code
    {% import 'appbuilder/baselib.html' as baselib %}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/init.html", line 46, in top-level template code
    {% block body %}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/baselayout.html", line 19, in block "body"
    {% block content %}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/general/model/list.html", line 7, in block "content"
    {% block list_search scoped %}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/general/model/list.html", line 8, in block "list_search"
    {% call lib.accordion_tag("accordion1",_("Search"), False) %}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/jinja2/runtime.py", line 679, in _invoke
    rv = self._func(*arguments)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/general/lib.html", line 291, in template
    {{ caller() }}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/jinja2/runtime.py", line 679, in _invoke
    rv = self._func(*arguments)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/templates/appbuilder/general/model/list.html", line 9, in template
    {{ widgets.get('search')()|safe }}
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/flask_appbuilder/widgets.py", line 114, in __call__
    label_columns[col] = as_unicode(self.template_args["form"][col].label.text)
  File "/home/konrad/projekte/hito/database-frontend/venv/lib/python3.8/site-packages/wtforms/form.py", line 64, in __getitem__
    return self._fields[name]
KeyError: 'sourceuris'

The error persists even when I remove 'sourceuris' from the list_columns array.

How can I get Flask AppBuilder to display arrays without errors?

Edit: I implemented the suggestion of @mehdy, however creating doesn't work and on edit I cannot change the size of the array. See the screenshots below:

View

Viewing works fine. viewing works fine

Edit

Editing only works if the array size stays the same. editing only works if the array size stays the same

Create

Creating doesn't work because the array is initially empty and I cannot increase the size to even one element.

creating doesn't work because the array is initially empty and I cannot increase the size to even one element

Note that the array in the real case is called "synonyms", not "sourceuris" as in the minimal example.

1 Answers

The problem is caused by search form fields. To avoid that you can exclude sourceuris from search form fields as follow.

    search_exclude_columns = ['sourceuris']

But since Flask-AppBuilder doesn't support Array fields, you have to add these to attributes as well to get it to work.

from wtforms import FieldList, StringField

add_form_extra_fields = {'sourceuris': FieldList(StringField('Source URIs'), min_entries=1)}
edit_form_extra_fields = {'sourceuris': FieldList(StringField('Source URIs'), min_entries=1)}

All these three attributes have to be added to your ModelView class.

Related