Как создать немного более сложный фильтр, используя or_ или and_ в sqlalchemy

Я пытаюсь сделать очень простой поиск из списка терминов

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

Как я программно просматриваю список терминов и строю «условия» из списка терминов, чтобы я мог сделать запрос с помощью фильтра и или_ или _and?

  • истощенные итераторы - что с ними делать?
  • Python: проверьте, является ли один словарь подмножеством другого более крупного словаря
  • эквивалент python фильтра (), получающий два выходных списка (т.е. раздел списка)
  • Python: фильтрация списков по индексам
  •  eg query.filter(or_(#something constructed from terms)) 

  • Как написать вывод в том же месте на консоли?
  • Как изменить пароль пользователя Linux из python
  • Как я могу выделить конкретные данные из открытого URL-адреса в Python с помощью urllib2?
  • формат координат matplotlib
  • Как добавить virtualenv в путь
  • Использование OR в SQLAlchemy
  • 4 Solutions collect form web for “Как создать немного более сложный фильтр, используя or_ или and_ в sqlalchemy”

    Если у вас есть список терминов и вы хотите найти строки, в которых поле соответствует одному из них, вы можете использовать метод in_ ():

     terms = ['term1', 'term2', 'term3'] query.filter(Cls.field.in_(terms)) 

    Если вы хотите сделать что-то более сложное, то or_() и and_() принимают объекты ClauseElement качестве параметров. ClauseElement и его подклассы в основном представляют SQL AST вашего запроса. Как правило, вы создаете элементы предложения, вызывая оператор сравнения объектов Column или InstrumentedAttribute:

     # Create the clause element clause = (users_table.columns['name'] == "something") # you can also use the shorthand users_table.c.name # The clause is a binary expression ... print(type(clause)) # <class 'sqlalchemy.sql.expression._BinaryExpression'> # ... that compares a column for equality with a bound value. print(type(clause.left), clause.operator, type(clause.right)) # <class 'sqlalchemy.schema.Column'>, <built-in function eq>, # <class 'sqlalchemy.sql.expression._BindParamClause'> # str() compiles it to SQL print(str(clause)) # users.name = ? # You can also do that with ORM attributes clause = (User.name == "something") print(str(clause)) # users.name = ? 

    Вы можете обрабатывать элементы предложения, представляющие ваши условия, такие как любые объекты Python, помещать их в списки, составлять их в другие элементы предложения и т. Д. Таким образом, вы можете сделать что-то вроде этого:

     # Collect the separate conditions to a list conditions = [] for term in terms: conditions.append(User.name == term) # Combine them with or to a BooleanClauseList condition = or_(*conditions) # Can now use the clause element as a predicate in queries query = query.filter(condition) # or to view the SQL fragment print(str(condition)) # users.name = ? OR users.name = ? OR users.name = ? 

    Предполагая, что переменная terms содержит действительные фрагменты операторов SQL, вы можете просто передать terms предшествует звездочка, к or_ или or_ :

     >>> 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) 

    хорошо у меня была такая же проблема: SQLAlchemy: эффективный / лучший выбор по первичным ключам?

     terms = ['one', 'two', 'three'] clauses = or_( * [Table.field == x for x in terms] ) query = Session.query(Table).filter(clauses) 

    Тебе нравится это?

    Вы можете использовать:

    http://docs.sqlalchemy.org/en/rel_0_8/core/tutorial.html#conjunctions

    В документации abobe вы найдете, как комбинировать условия. И, Или и не …!

    Python - лучший язык программирования в мире.