65

I want to create query in sql alchemy filter, but column is(dynamic) in variable/specified in variable.

Original Query:

db_session.query(Notice).filter(Notice.subject.like("%" +query+ "%"))

I want to do query like this:

col_name='subject'
db_session.query(Notice).filter(Notice.col_name.like("%" +query+ "%"))
col_name='status'
status=0
db_session.query(Notice).filter(Notice.col_name != 1)

4 Answers 4

95

Just use getattr standard python library function to get an attribute by name:

col_name = 'subject'
db_session.query(Notice).filter(getattr(Notice, col_name).like("%" + query + "%"))
Sign up to request clarification or add additional context in comments.

2 Comments

to my understanding "Notice" here is a python Class? as a sqlarchemy data model? As a table in the database??
Notice is a python class, and is a mapped sqlalchemy model. So in the first example from Classical Mapping it would be User, not user.
22

In newer sqlalchemy version, it should be done this way:

Notice.__table__.c[col_name]

So:

(db_session
    .query(Notice)
    .filter(Notice.__table__.c[col_name].like("%" + query + "%")
)

4 Comments

I'm not convinced that anything here is specific to newer SQLAlchemy versions. What's your basis for that claim? What functionality here didn't exist in older versions?
Note that you can use .columns instead of .c, which is perhaps clearer.
This is not related to version. You're accessing the Column objects from the underlying Table, instead of the instrumented attributes of the mapped class. This might not even work, if the mapped attribute is named differently from the column.
I think your filter is missing a closing parenthesis.
4

I tried @vans solution but it didn't work. I always got an AttributeError complaining that my table didn't have that column. What worked for me was table.columns:

getattr(Notice.columns,col_name)

1 Comment

This is because the question queries on an ORM mapped python class whereas you are querying on a Table instance.
-3

The accepted answer has a solution, but an outdated one.

SQLAlchemy 1.3 suggests putting all text filters in text(), joined with and. Docs

Example: session.query(User).filter(text("id<224")).order_by(text("id")).all()

Another example from docs on a different query

>>> s = select([
...        text("users.fullname || ', ' || addresses.email_address AS title")
...     ]).\
...         where(
...             and_(
...                 text("users.id = addresses.user_id"),
...                 text("users.name BETWEEN 'm' AND 'z'"),
...                 text(
...                     "(addresses.email_address LIKE :x "
...                     "OR addresses.email_address LIKE :y)")
...             )
...         ).select_from(text('users, addresses'))

2 Comments

Make sure you're not vulnerable to SQL injection if you put dynamic things in the text()...
I think you missed the point of the question. Using SQL text and passing a model attribute name as a string are separate things. This Q/A seems mostly about the latter, and there's nothing outdated about the accepted answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.