假设我们在某些Models.py文件中具有以下代码:
.vocabulary_
我们想使用自动映射库来反映这些模型,因此我们将这段代码存储在另一个名为Database.py的模块中:
class Person(db.Model):
__tablename__ = 'Persons'
ID = db.Column(db.Integer, primary_key=True, nullable=False)
Name = db.Column(db.String(255), nullable=False)
class House(db.Model):
__tablename__ = 'Houses'
ID = db.Column(db.Integer,primary_key=True,nullable=False)
OwnerID = db.Column(db.Integer, nullable=False)
TenantID = db.Column(db.Integer, nullable=False)
__table_args__ = (
db.ForeignKeyConstraint(
['OwnerID'],
['Persons.ID'],
),
db.ForeignKeyConstraint(
['TenantID'],
['Persons.ID'],
),
)
OwnerBackref = db.relationship('Person', backref='OwnerBackref', lazy=True, foreign_keys=[OwnerID])
TenantBackref = db.relationship('Person', backref='TenantBackref', lazy=True, foreign_keys=[TenantID])
现在,当我在其他模块中导入House时,我希望能够做到这一点:
Base = automap_base()
engine = create_engine(DB_CONNECTION, pool_size=10, max_overflow=20)
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
Base.prepare(engine, reflect=True)
Person = Base.classes.Persons
House = Base.classes.Houses
但是,我收到一条错误消息,说那2个反向引用不存在,而是将一个名为“ persons”的字段添加到了我的House对象,但是这里的问题是它只链接了1个(租户或所有者)。我的意思是,如果我这样做:
h = db_session.query(House).first()
print(h.OwnerBackref.Name)
print(h.TenantBackref.Name)
它将仅打印相应租户的姓名,或者为所有者打印姓名,而使我无法访问另一方的信息。 (请注意,这里没有设置我设置为反向引用的名称)
所以,我的问题是如何使用创建的后向引用访问所需的信息? 我在这里做错了吗?
答案 0 :(得分:0)
代码中的错误是您正在使用foreign_keys=
来定义表之间的关系,但是您正在将本地键名而不是外键名传递给该函数。对于您的代码,您不能使用foreign_keys=
在House模型中定义关系,因为只有一个可能的外键Person.ID
,但是有两个可能的本地键House.OwnerID
和House.TenantID
。应该使用primaryjoin=
参数来指定它。
class Person(db.Model):
__tablename__ = 'Persons'
ID = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.String(255), nullable=False)
class House(db.Model):
__tablename__ = 'Houses'
ID = db.Column(db.Integer,primary_key=True)
OwnerID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)
TenantID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)
Owner = db.relationship('Person', backref='HousesOwned', primaryjoin='House.OwnerID == Person.ID')
Tenant = db.relationship('Person', backref='HousesOccupied', primaryjoin='House.TenantID == Person.ID')
如果将关系语句放置在Person模型而不是House模型中,则可以使用foreign_keys=
或primaryjoin=
来定义关系。下面的代码将产生与前面的代码完全相同的关系。
class Person(db.Model):
__tablename__ = 'Persons'
ID = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.String(255), nullable=False)
HousesOwned = db.relationship('House', backref='Owner', foreign_keys='[House.OwnerID]')
HousesOccupied = db.relationship('House', backref='Tenant', foreign_keys='[House.TenantID]')
class House(db.Model):
__tablename__ = 'Houses'
ID = db.Column(db.Integer,primary_key=True)
OwnerID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)
TenantID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)