Reputation: 10213
I am using sqlalchemy ORM layer to communicate with RDS. Here this is common function for all tables to filter row. We pass table name, column to select, filters and date range.
filter = { "company_guid": "xxxx", "status": "Active"}
filter
is dictionary which have key as column name and value is condition.
Which work fine
but know I want filter on status
column where value can be Active
or TempInActive
So now filter become filter = { "company_guid": "xxxx", "status": ["Active", "TempActive"}
It not working because value is list, not string.
I know can use result = session.query(Customers).filter(Customers.id.in_([1,3]))
but in my scenario table name and column names are function arguments.
def get_items_withvalue(self, table_name, column_name=None, attribute_value=None,
columns_to_select=None, date_value=False, filters=None):
"""
@Summary: This method used to get data based on a condition.
@param table_name (string): This is the table_name
@param column_name (None/string): for the column_name
@param attribute_value (None/list/string): for the column_value
@params columns_to_select(None/list/string): columns to send in response
@params filters(None/dict): where clause for rows to be fetched
@return (list of dict): fetched rows or count from DB
"""
data = []
session = None
try:
# Get session which communicate with RDS
session = self.get_session()
table = str_to_class(table_name)
if columns_to_select:
data = []
else:
if isinstance(attribute_value, list):
data = (session.query(table)
.filter(getattr(table, column_name)
.in_(attribute_value))
.all())
elif date_value:
data = (session.query(table)
.filter(cast(getattr(table, column_name), Date)
== attribute_value)
.all())
elif filters:
## How to update following code to filter on list(in)
# filters is dictionary
data = (session.query(table).filter_by(**filters).all())
##
else:
data = (
session.query(table).filter(getattr(table, column_name)
== attribute_value).all()
)
except Exception as err:
self.logger.exception("Error fetching items ")
raise Exception(err)
finally:
if session:
session.close()
if columns_to_select:
return [row._asdict() for row in data]
return [object_as_dict(row) for row in data]
Can anyone help me to solve this?
One way is to construct query string and do eval, but which is not good way.
Upvotes: 1
Views: 3033
Reputation: 958
Extending the above answer just with a list
of conditions
filters = [orm_table_object.field_name_1 == expected_value_1]
if expected_value_2 is not None:
filters.append(orm_table_object.field_name_2 == expected_value_2)
if expected_value_3 is not None:
filters.append(orm_table_object.field_name_3 == expected_value_3)
session.query(table).filter(
*[f for f in filters]
)
Upvotes: 1
Reputation: 10861
As you are using the ORM I'll assume that what you call table
in the function is actually a mapped ORM class.
If I understand correctly, you want to be able to handle both cases where the values of filters
may be either a scalar value, in which case you'd like to filter on equality, or a list of values, in which case you'd like to test for presence in the list using in_()
. However, a complicating factor is that you cannot use the str
keys of filters
directly in filter()
. Hopefully I've understood.
I think you can solve this neatly by using getattr
to get the column attribs from the table object, a conditional list comprehension and then unpacking the list into .filter()
, for example:
filters = {'a': 'scalar', 'and': ['collection', 'of', 'values']}
(
session.query(table).filter(
*[
getattr(table, k).in_(v)
if isinstance(v, list)
else getattr(table, k) == v
for k, v in filters.items()
]
)
)
This will produce the equivalent of orm_table_object.column_attrib == val
if val
is not a list
, and orm_table_object.column_attrib.in_(val)
if val
is a list
.
Upvotes: 3