简体   繁体   中英

Get all columns from a SqlAlchemy table to filter on them

I build default equal filters for all columns of the table and then add/override only specific filters I want on a few columns, like this:

# Table definition

class OrderTable(Base):
    __tablename__ = "orders"

    id = Column(Integer, unique=True, nullable=False, primary_key=True)
    name = Column(String, nullable=False)

# Build all default filters for this table

table_filters = {column.name: lambda value: column == value for column in OrderTable.__table__.columns}

# Add/override specific filters

all_filters = {**table_filters, "name": lambda value: OrderTable.name.like(value)}

# Execute the query

query = ...
query = query.filter(all_filters["id"](123)) 
query.delete()

But I get this warning when using default filters:

SAWarning: Evaluating non-mapped column expression 'orders.id' onto ORM instances; this is a deprecated use case.  Please make use of the actual mapped columns in ORM-evaluated UPDATE / DELETE expressions.

Is there a better way to get all columns to be able to filter on them without getting this warning?

I tried different ways of gettings all columns for a table with OrderTable.__mapper__.attrs and inspect(OrderTable).attrs but then the filters do not work.

I am not used to post so please tell me if I can improve my question and I will edit it.

It appears to be related to fetching columns from the table vs using attributes directly.

When you use the attibute directly, you get an InstrumentedAttribute , when you get the column from __table__.columns you get a Column .

With the Column you get that warning:

id_filter_col = OrderTable.__table__.c["id"] == 1

query = session.query(OrderTable)
query = query.filter(id_filter_col)
query.delete()  # SAWarning: Evaluating non-mapped column expression 'orders.id' onto ORM instances...

But now when you use the InstrumentedAttribute :

id_filter_attr = OrderTable.id == 2

query = session.query(OrderTable)
query = query.filter(id_filter_attr)
query.delete()  # OK

You can access the attributes from the mapper via __mapper__.all_orm_descriptors , which should solve your problem.

class OrderTable(Base):
    __tablename__ = "orders"

    id = Column(Integer, unique=True, nullable=False, primary_key=True)
    name = Column(String, nullable=False)

table_filters = {column.key: lambda value: column == value for column in OrderTable.__mapper__.all_orm_descriptors}

all_filters = {**table_filters, "name": lambda value: OrderTable.name.like(value)}

query = ...
query = query.filter(all_filters["id"](123)) 
query.delete()  # OK

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM