How to construct a slightly more complex filter using “or_” or “and_” in SQLAlchemy

前端 未结 4 942
北海茫月
北海茫月 2020-12-25 12:16

I\'m trying to do a very simple search from a list of terms

terms = [\'term1\', \'term2\', \'term3\']

How do I programmatically go through

4条回答
  •  情深已故
    2020-12-25 12:27

    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='spam@eggs.com'"]
    >>> print or_(*terms)
    name='spam' OR email='spam@eggs.com'
    >>> print and_(*terms)
    name='spam' AND email='spam@eggs.com'
    

    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 == 'spam@eggs.com']
    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)
    

提交回复
热议问题