Assuming that your terms
variable contains valid SQL statement fragments, you can simply pass terms
preceded by an asterisk to or_
or and_
:
>>> from sqlalchemy.sql import and_, or_
>>> terms = ["name='spam'", "email='[email protected]'"]
>>> print or_(*terms)
name='spam' OR email='[email protected]'
>>> print and_(*terms)
name='spam' AND email='[email protected]'
Note that this assumes that terms
contains only valid and properly escaped SQL fragments, so this is potentially unsafe if a malicious user can access terms
somehow.
Instead of building SQL fragments yourself, you should let SQLAlchemy build parameterised SQL queries using other methods from sqlalchemy.sql
. I don't know whether you have prepared Table
objects for your tables or not; if so, assume that you have a variable called users
which is an instance of Table
and it describes your users
table in the database. Then you can do the following:
from sqlalchemy.sql import select, or_, and_
terms = [users.c.name == 'spam', users.c.email == '[email protected]']
query = select([users], and_(*terms))
for row in conn.execute(query):
# do whatever you want here
Here, users.c.name == 'spam'
will create an sqlalchemy.sql.expression._BinaryExpression
object that records that this is a binary equality relation between the name
column of the users
table and a string literal that contains spam
. When you convert this object to a string, you will get an SQL fragment like users.name = :1
, where :1
is a placeholder for the parameter. The _BinaryExpression
object also remembers the binding of :1
to 'spam'
, but it won't insert it until the SQL query is executed. When it is inserted, the database engine will make sure that it is properly escaped. Suggested reading: SQLAlchemy's operator paradigm
If you only have the database table but you don't have a users
variable that describes the table, you can create it yourself:
from sqlalchemy import Table, MetaData, Column, String, Boolean
metadata = MetaData()
users = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column('name', String),
Column('email', String),
Column('active', Integer)
)
Alternatively, you can use autoloading which queries the database engine for the structure of the database and builds users
automatically; obviously this is more time-consuming:
users = Table('users', metadata, autoload=True)