Sqlalchemy+elixir: как запросить отношения ManyToMany?
Я использую sqlalchemy с Elixir и у меня возникают проблемы при попытке сделать запрос..
У меня есть 2 лица, Customer и CustomerList, со многими ко многим отношениям.
customer_lists_customers_table = Table('customer_lists_customers',
metadata,
Column('id', Integer, primary_key=True),
Column('customer_list_id', Integer, ForeignKey("customer_lists.id")),
Column('customer_id', Integer, ForeignKey("customers.id")))
class Customer(Entity):
[...]
customer_lists = ManyToMany('CustomerList', table=customer_lists_customers_table)
class CustomerList(Entity):
[...]
customers = ManyToMany('Customer', table=customer_lists_customers_table)
Я пытаюсь найти CustomerList с некоторым клиентом:
customer = [...]
CustomerList.query.filter_by(customers.contains(customer)).all()
Но я получаю ошибку: NameError:
глобальное имя "клиенты" не определено
Кажется, что клиенты не связаны с полями сущностей, есть ли специальная форма запроса для работы со связями (или связями ManyToMany)?
Спасибо
3 ответа
Вы можете использовать обычный фильтр: query.filter(CustomerList.customers.contains(customer))
, См. Документацию SQLAlchemy для большего количества примеров. Это фактически filter_by, это особый случай. query.filter_by(**kwargs)
стенография работает только для простых сравнений равенства. Под прикрытием query.filter_by(foo="bar", baz=42)
делегирован в эквивалент query.filter(and_(MyClass.foo == "bar", MyClass.baz == 42))
, (На самом деле есть немного больше магии, чтобы выяснить, какое свойство вы имели в виду, у вас много сущностей, но оно все еще использует простое делегирование)
Внимательно прочитайте сообщение об ошибке, оно указывает на источник проблемы. Ты имел ввидуCustomerList.query.filter_by(CustomerList.customers.contains(customer)).all()
?
Обновление: при использовании декларативного определения вы можете использовать только что определенные отношения в области видимости класса, но эти свойства не видны вне класса:
class MyClass(object):
prop1 = 'somevalue'
prop2 = prop1.upper() # prop1 is visible here
val2 = MyClass.prop1 # This is OK
val1 = prop1.lower() # And this will raise NameError, since there is no
# variable `prop1` is global scope
CustomerList.query.filter_by(CustomerList.customers.contains(customer)).all()
должно работать нормально.