Sqlalchemy+elixir:如何查询多对多关系?

1 投票
3 回答
1926 浏览
提问于 2025-04-15 22:35

我在用sqlalchemy和Elixir的时候遇到了一些问题,想要做一个查询。

我有两个实体,客户(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)

我想找到某个客户的客户列表:

customer = [...]
CustomerList.query.filter_by(customers.contains(customer)).all()

但是我遇到了这个错误: NameError:

全局名称 'customers' 未定义

看起来 'customers' 和实体字段没有关系,处理这种关系(或者多对多关系)有没有特别的查询方式呢?

谢谢

3 个回答

0

CustomerList.query.filter_by(CustomerList.customers.contains(customer)).all() 这段代码应该可以正常运行。

1

仔细阅读错误信息,它会告诉你问题出在哪里。你是不是想写成 CustomerList.query.filter_by(CustomerList.customers.contains(customer)).all() 呢?

更新:当你使用声明式定义时,可以在 class 的范围内使用刚定义的关系,但这些属性在类外是看不见的:

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
1

你可以使用普通的过滤器: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))的。(其实还有一点小技巧来判断你指的是哪个属性,特别是当你有很多实体的时候,但它仍然是用简单的委托方式来处理的)

撰写回答