正确的访问SQLAlchemy的关系

问题描述 投票:0回答:1

下面的示例代码(基于SQLAlchemy ORM tutorial):

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.orm import sessionmaker
from sqlalchemy import func

engine = create_engine('sqlite:///:memory:')

Session = sessionmaker(bind=engine)

Base = declarative_base()

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

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

Base.metadata.create_all(engine)


if __name__ == "__main__":

    session = Session()
    query = session.query(func.count(User.id)).join(User.addresses)

运行良好的之前的0.8版本SQLAlchemy的。但是,对于版本> = 0.8时,它产生了以下错误:

AttributeError: type object 'User' has no attribute 'addresses'

这不会的情况下,最后一行是发生:

    query = session.query(User).join(User.addresses)

然而,func表达的使用是the preferred way to issue 'count' queries根据SQLAlchemy的文档(以及也参见zzzeek's answer here)。它真正的问题在大表的情况。

所以,我明白,这个问题是因为在new way relationships work since version 0.8的。现在的问题是,什么应该是正确的(也是最有效的)的方式来“强制” backref初始化。

注:与映射的类作为参数发出的第一个查询后,backrefs将被初始化,这样所有其他的查询将不会面临上述问题。问题的关键是,在发出func.count查询时,我不知道是否backrefs已经初始化或没有(即这是第一次发出查询)。

python sqlalchemy
1个回答
1
投票

你举的例子是完全一样的,在SQLAlchemy的文档的Linking Relationships with Backref部分。第二个代码块显示了使用equivalent参数的back_populates版本。但是,在这种情况下,关系的双方都初始化和您的查询应该工作。随着order_by你的模型应该是这样的:

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    addresses = relationship("Address", order_by="Address.id", back_populates="user")


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", back_populates="addresses")
© www.soinside.com 2019 - 2024. All rights reserved.