SQLAlchemy示例“处理多个联接路径”会引发异常

时间:2013-07-05 07:44:00

标签: python database sqlalchemy

我尝试做类似于以下示例的事情:

http://docs.sqlalchemy.org/en/rel_0_8/orm/relationships.html#handling-multiple-join-paths

当我执行以下脚本时:

#!/usr/bin/python
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.orm import aliased

engine = create_engine('sqlite:///demo.db', echo=True)
Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    password = Column(String)

    def __init__(self, name, fullname, password):
        self.name = name
        self.fullname = fullname
        self.password = password

    def __repr__(self):
        return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)

class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    email_address = Column(String, nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'))

    user = relationship("User", backref=backref('addresses', order_by=id),     passive_deletes=True)
    user2 = relationship("User", backref=backref('addresses2', order_by=id), passive_deletes=True)

    def __init__(self, email_address):
        self.email_address = email_address

    def __repr__(self):
        return "<Address('%s')>" % self.email_address

class Customer(Base):
    __tablename__ = 'customer'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    billing_address_id = Column(Integer, ForeignKey("addresses.id"))
    shipping_address_id = Column(Integer, ForeignKey("addresses.id"))

    billing_address = relationship("Address", foreign_keys=[billing_address_id])
    shipping_address = relationship("Address", foreign_keys=[shipping_address_id])

    def test():
        print "Testing .."
        # Test code.

    if __name__ == '__main__':
        test()

我得到了

2013-06-30 12:56:53,938 INFO sqlalchemy.engine.base.Engine PRAGMA     table_info("users")
2013-06-30 12:56:53,938 INFO sqlalchemy.engine.base.Engine ()
2013-06-30 12:56:53,939 INFO sqlalchemy.engine.base.Engine PRAGMA table_info("addresses")
2013-06-30 12:56:53,940 INFO sqlalchemy.engine.base.Engine ()
2013-06-30 12:56:53,940 INFO sqlalchemy.engine.base.Engine PRAGMA table_info("customer")
2013-06-30 12:56:53,940 INFO sqlalchemy.engine.base.Engine ()
Traceback (most recent call last):
  File "./test.py", line 131, in <module>
test()
  File "./test.py", line 70, in test
ed_user = User('ed', 'Ed Jones', 'edspassword')
  File "<string>", line 2, in __init__
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/instrumentation.py", line 309, in _new_state_if_none
state = self._state_constructor(instance, self)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py", line 494, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/instrumentation.py", line 157, in _state_constructor
self.dispatch.first_init(self, self.class_)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/event.py", line 377, in __call__
fn(*args, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 2347, in _event_on_first_init
configure_mappers()
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 2263, in configure_mappers
mapper._post_configure_properties()
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 1172, in _post_configure_properties
prop.init()
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/interfaces.py", line 128, in init
self.do_init()
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/properties.py", line 911, in do_init
self._determine_joins()
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/properties.py", line 1048, in _determine_joins
% self)
sqlalchemy.exc.ArgumentError: Could not determine join condition between parent/child tables on relationship Customer.billing_address.  Specify a 'primaryjoin' expression.     If 'secondary' is present, 'secondaryjoin' is needed as well.

我希望这个例子可以开箱即用,而不必将primaryjoin作为参数添加到relationship()。

1 个答案:

答案 0 :(得分:1)

我要说的不是SQLAlchemy 0.8,它可能是0.7版本。确保你的版本是0.8,在以前的版本中,你需要在更多情况下使用primaryjoin(参见http://docs.sqlalchemy.org/en/rel_0_8/changelog/migration_08.html#rewritten-relationship-mechanics