Python - 类在赋值之前引用另一个类

时间:2017-07-25 19:29:44

标签: python orm sqlalchemy

我正在使用sqlalchemy的ORM来创建映射到SQL表的类。我遇到了生成这些类之间关系的问题,因为它们在声明类之前相互引用。当我运行代码时,解释器会抱怨NameError: name 'Account' is not defined

我在下面添加了一个代码示例,演示了我如何声明这些类。

class Location(Base):
    __tablename__ = 'locations'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    address = Column(String)
    city = Column(String)
    state = Column(String)
    zip_code = Column(String)

    account = sa.orm.relationship('Account', order_by=Account.id, back_populates='location')
    entity = sa.orm.relationship('Entity', order_by=Entity.id, back_populates='location')

    def __repr__(self):
        return "<Location(name='{}', address='{}', city='{}', state='{}', zip_code='{}')>".\
                    format(self.name, self.address, self.city, self.state, self.zip_code)


class Account(Base):
    __tablename__ = 'accounts'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    number = Column(String)
    institution = Column(String)
    # entity_id   = Column(Integer, sa.ForeignKey('entities.id'))

    entity = sa.orm.relationship('Entity', back_populates='accounts')
    location = sa.orm.relationship('Location', order_by=Location.id, back_populates='account')

    def __repr__(self):
        return "<Account(name='{}', account={}, institution={}, entity={})>".\
                format(self.name, self.number, self.institution, self.entity)


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

    accounts = sa.orm.relationship('Account', order_by=Account.id, back_populates='entity')
    location = sa.orm.relationship('Location', order_by=Location.id, back_populates='entity')

    def __repr__(self):
        return "<Entity(name='{}', location='{}')>".format(self.name, self.location)

我在这里缺少什么?有没有办法定义所有类,然后尽可能使用函数调用它们?例如,对于函数,在定义了所有函数后,在底部调用main很简单:

def main():
    foo()

def foo():

if __name__=='__main__':
    main()

1 个答案:

答案 0 :(得分:0)

将您的排序定义为callables或表达式字符串,如relationship API documentation中所述:

IterableIterator

class Location(Base):
    ...
    account = sa.orm.relationship('Account',
        order_by=lambda: Account.id, ...)

问题是在评估位置等级时会出现问题。 body名称Account在全局范围内尚不存在,并且未在类主体的本地范围中定义。传递函数/ lambda允许将评估推迟到&#34;映射器初始化时间&#34;:

  

class Location(Base): ... account = sa.orm.relationship('Account', order_by='Account.id', ...) 接受的一些参数可选地接受一个可调用函数,该函数在被调用时产生所需的值。在“映射器初始化”时,父relationship()调用callable,这仅在第一次使用映射器时发生,并且假定在构建了所有映射之后。这可用于解决声明顺序和其他依赖性问题,例如Mapper是否在同一文件中Child下面声明

传递字符串也将解决声明顺序问题,并提供另一个功能:

  

使用Declarative类注册表作为命名空间,将这些字符串参数转换为将字符串作为Python代码进行计算的callables。这允许通过字符串名称自动查找相关类,根本不需要将相关类导入本地模块空间