Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a sqlalchemy query using a string variable as table name?

I apologize in advance if I am not clear, English is not my native language. Feel free to tell me if I make too many mistakes :)

I am a newbie in using flask_sqlalchemy and get frustrated after spending hours on Internet searching for an answer.

What I want is doing a query like that one :

ModelName.query.filter_by(name='something').all()

But instead of using ModelName I want to do something like that :

model_list = ['Model1', 'Model2', 'Model3']
for model in model_list:
    some_var = model.query.filter_by(name='something').all()
    # do some stuff with the variable

The error is :

'str' object has no attribute 'query'

I have of course the same kind of problem when trying to use db.session.add() with a string variable.

I understand that the query requires some kind of _BoundDeclarativeMeta object instead of a string but then how to get that object from a list to pass it to a for loop ?

I tryed using 'db.metadata.tables[my_variable]' but I get a Table object instead of a _BoundDeclarativeMeta object and it doesn't work the same.

I manage to do a query using

db.session.query(db.metadata.tables[my_variable])

instead of

my_variable.query

but I can't use that method for the 'db.session.add()' (or is it possible ?)

Is there any way to 'cast' the string variable into the right type of sqlalchemy object ?

like image 296
cleve21 Avatar asked Dec 16 '16 01:12

cleve21


1 Answers

I needed a way to query by referring to the model's tablename. This is what I came up with:

class Model1(db.Model):
    __tablename__ = 'table1' # or whatever, doesn't matter

class Model2(db.Model):
    __tablename__ = 'table2'

tables_dict = {table.__tablename__: table for table in db.Model.__subclasses__()}

def table_object(table_name):
    return tables_dict.get(table_name)

Then, use it like this:

model_list = ['table1', 'table2']
for model in model_list:
    some_var = db.session.query(table_object(table_name=model)).filter_by(name='something').all()

The important bit is db.Model.__subclasses__() - gives a list of the model classes (objects?).

like image 122
timothyh Avatar answered Oct 03 '22 12:10

timothyh