如何在SQLAlchemy方法中将参数作为过滤条件传递

时间:2017-03-18 14:01:11

标签: python sqlalchemy

我知道,我可以使用Python的SQLAlchemy的查询方法如下:

session.query(User).filter(User.id == 0).first()

但是我想参数化它,所以我可以传递一个表名,过滤元素和过滤值来查询,例如:

filter element -> User.id
filter value -> 0

但是当我将User.filter_element传递给查询时,我得到一个例外:

AttributeError: type object 'User' has no attribute 'filter_element'

我正在尝试做什么,如果是这样的话?

请注意,我知道我可以使用sql.execute(<sql>)来获得类似的结果,但我更喜欢使用sqlalchemy.orm来执行此操作而无需使用SQL语句。

2 个答案:

答案 0 :(得分:1)

通过这些信息,您可以灵活地生成查询。

In [2]: User.email
Out[2]: <sqlalchemy.orm.attributes.InstrumentedAttribute at 0x7f42cd4b7410>

In [3]: User.email == ''
Out[3]: <sqlalchemy.sql.elements.BinaryExpression object at 0x7f42ca640550>

In [4]: User.email.in_([])
...warning
Out[4]: <sqlalchemy.sql.elements.BinaryExpression object at 0x7f42c9e07710>

你可以做到

user_attribute = getattr(User, 'email') # get attribute
if equals_filter:
    user_filter = user_attribute == equals_value # compute expression
else:
   user_filter = user_attribute.in_(in_list)
users = session.query(User).filter(user_filter) # filter using expression

答案 1 :(得分:0)

你可以使用。 declarative_basefilter_by

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String

engine = create_engine('sqlite:///test.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()


class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(50), unique=True)

    def __init__(self, name=None):
        self.name = name

    def __repr__(self):
        return '<User %r>' % (self.name)

Base.metadata.create_all(bind=engine)
db_session.add(User('name1'))
db_session.commit()

User.query.filter_by(name='name1').first()  # => <User u'name1'>