0

I define a specific Flask Table as follows

class MyTable(Table):

    def __init__(self, table_id, rows):
        self.table_id = table_id
        super().__init__(rows)
    
    Code = Col('Code', column_html_attrs = {'class': 'apply-filter'})

Now, if I try to generalize it by moving the Code attribute inside the __init__,

def __init__(self, table_id, rows, key):
    self.table_id = table_id
    self.__dict__[key] = Col(key, column_html_attrs = {'class': 'apply-filter'})
    super().__init__(rows)

something goes wrong and it is no longer shown.

I've also tried with self.Code = ... (that is not what I want because it is not generalized) but it also fails.

Conceptual question

Even if I've found a working answer, I'm still not fully satisfied with it. Why wasn't my original code good as well? Doesn't the constructor of the parent class see the fields (dynamically) created in the initialization of the derived class?

1 Answers1

0

Found the relevant example, by looking for __init__ inside github source code of Flask Table. In my case I can do

def __init__(self, table_id, rows, key):
    super().__init__(rows)
    self.table_id = table_id
    self.add_column(key, Col(key, column_html_attrs = {'class': 'apply-filter'}))

that becomes, more generally:

class MyTable(Table):
    def __init__(self, table_id, rows, keys):
        super().__init__(rows)
        self.table_id = table_id
        for k in keys:
            self.add_column(k, Col(k, column_html_attrs = {'class': 'apply-filter'}))

Conceptual answer

Doesn't the constructor of the parent class see the fields (dynamically) created in the initialization of the derived class?

No, because the parent class has a metaclass that wants to read the attributes from the __new__ and the metaclass is executed at import time when those dynamic fields are not present.

Tl;dr

For the sake of it, you can recover the metaclass as table.TableMeta by importing table

from flask_table import Table, Col, table

Then you could do

class MyTable(Table):
    def __init__(self, table_id, rows, keys, filters):
        dict = {}
        for k in keys:
            if k in filters:
                dict[k] = Col(k, column_html_attrs = {'class': 'apply-filter'})
            else: 
                dict[k] = Col(k)
        metadict = table.TableMeta.__new__(table.TableMeta, 'MyTable', (Table,), dict).__dict__
        self.__dict__.update(metadict)
        super().__init__(rows)
        self.table_id = table_id

executive summary

The above would work but it is only the conceptual answer in order to deeply understand what is going on.

In the real-world scenario, you simply have to carefully read the full README of the github repo. There is a paragraph Dynamically Creating Tables, just follow the instructions, there is a convenient create_table that can be followed by add_column, as you have finally discovered.