Предполагая, что ваша переменная terms
содержит допустимые фрагменты операторов SQL, вы можете просто передать terms
, которому предшествует звездочка, or_
или and_
:
>>> from sqlalchemy.sql import and_, or_
>>> terms = ["name='spam'", "email='spam@eggs.com'"]
>>> print or_(*terms)
name='spam' OR email='spam@eggs.com'
>>> print and_(*terms)
name='spam' AND email='spam@eggs.com'
Обратите внимание, что это предполагает, что terms
содержит только допустимые и правильно экранированные фрагменты SQL, поэтому это потенциально небезопасно, если злонамеренный пользователь может каким-либо образом получить доступ к terms
.
Вместо того, чтобы создавать фрагменты SQL самостоятельно, вы должны позволить SQLAlchemy создавать параметризованные запросы SQL, используя другие методы из sqlalchemy.sql
. Я не знаю, подготовили ли вы Table
объекты для ваших таблиц или нет; если это так, предположим, что у вас есть переменная с именем users
, которая является экземпляром Table
и описывает вашу таблицу users
в базе данных. Тогда вы можете сделать следующее:
from sqlalchemy.sql import select, or_, and_
terms = [users.c.name == 'spam', users.c.email == 'spam@eggs.com']
query = select([users], and_(*terms))
for row in conn.execute(query):
# do whatever you want here
Здесь users.c.name == 'spam'
создаст объект sqlalchemy.sql.expression._BinaryExpression
, который записывает, что это отношение двоичного равенства между столбцом name
таблицы users
и строковым литералом, который содержит spam
. Когда вы преобразуете этот объект в строку, вы получите фрагмент SQL, например users.name = :1
, где :1
- это заполнитель для параметра. Объект _BinaryExpression
также запоминает привязку :1
к 'spam'
, но не вставит его, пока не будет выполнен SQL-запрос. Когда он вставлен, ядро базы данных убедится, что оно правильно экранировано. Предлагаемое чтение: Парадигма оператора SQLAlchemy
Если у вас есть только таблица базы данных, но у вас нет переменной users
, которая описывает таблицу, вы можете создать ее самостоятельно:
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)
)
В качестве альтернативы вы можете использовать автозагрузку, которая запрашивает ядро базы данных о структуре базы данных и автоматически создает users
; очевидно, это занимает больше времени:
users = Table('users', metadata, autoload=True)