2

I'm developing my first Flask app using SQLAlchemy models, I've got around 10 classes representing database tables and the classes have fields representing columns.

Now in my app.py I'm trying to make a selection of data from the database and get it to have a form of a list of dictionaries (one dictionary representing a row):

[{'column_name1': 'data1', 'column_name2': 'data2', ...}, {'column_name1': 'data3', 'column_name2': 'data4', ...}, ...].

This is what I came up with but it doesn't work:

column_names = table.__table__.columns.keys()  # get columns names
records = table.query.whooshee_search(phrase).all()  # get table records

DATA = []

for record in records:
    row = {}
    for column_name in column_names:
        row[column_name] = record[column_name]
    DATA.append(row)

table is earlier assigned one of the classes, then column_names is a list of strings which are the names of the columns defined in this class. records is a list of table class objects which represent selected rows (that contain phrase). I checked displaying the results in html that this works fine and returns what is suppposed to return.

However, I'd like to have them as a dictionary created dynamically (so that I don't have to specify column names for every possible table value but make use of column_names). The line row[column_name] = record[column_name] seems to be the problem - I got the error

TypeError: 'User' object is not subscriptable

where User is one of the classes (the current value of table). row[column_name] = record.column_name was my another (silly) approach which of course didn't work either. One last thing to mention is that {{ record[column_name] }} was Jinja2 syntax I used when displaying the results in html.

Theta
  • 231
  • 2
  • 14

1 Answers1

2

Using Flask-SQLAlchemy the models defined do not contain a __getitem__(self, key) method by default hence you can not do table["some_key"].

One way would be to explicitly define a __getitem__(self, key) method in your model definitions. Here is a working example of it.

class User:
    def __init__(self):
        self.member = 0

    def __getitem__(self, field):
        return self.__dict__[field]

user = User()
print(user.member) # 0
print(user["member"]) # 0

Source:

  1. https://flask-sqlalchemy.palletsprojects.com/en/2.x/api/?highlight=model#models
  2. https://docs.python.org/3/reference/datamodel.html#object.getitem
onlinejudge95
  • 333
  • 3
  • 9
  • So this `__getitem__(self, key)` method needs to be defined once per class or separately for every class field? – Theta Nov 23 '19 at 20:45
  • 1
    Ok, I gave it a try in my project and it works exactly the way I wanted it to work, thanks a million! – Theta Nov 23 '19 at 21:15
  • @Theta you need to define this `__getitem__(self, key)` on each model you have. Maybe try doing something like this https://gist.github.com/onlinejudge95/2e00b39b7cc590bf384303ce41606ec1 – onlinejudge95 Nov 24 '19 at 00:19