[英]Self-referential foreign key relationship on SQLAlchemy declarative mixin class with declared_attr
我在SQLAlchemy应用程序的开始附近定义了一个mixin类,然后在我使用的几乎所有声明式模型上继承。
class Owned(object):
@declared_attr
def created_by_id(cls):
return Column(Integer, ForeignKey("accounts.id"),
nullable = True)
@declared_attr
def created_by(cls):
return relationship("Account", foreign_keys = cls.created_by_id)
@declared_attr
def updated_by_id(cls):
return Column(Integer, ForeignKey("accounts.id"),
nullable = True)
@declared_attr
def updated_by(cls):
return relationship("Account", foreign_keys = cls.updated_by_id)
这对于大多数预期的用例都适用。
class Thing(Owned, Base): # Base is from SQLAlchemy's declarative_base()
pass
account = session.query(Account).first()
thing = Thing(created_by = account, updated_by = account)
session.add(thing)
session.commit()
session.refresh(thing)
assert thing.created_by == account # pass
assert thing.updated_by == account # pass
但是,当我将Account
本身定义为继承自Owned
时,会出现意外行为。
class Account(Owned, Base):
pass
account_old = session.query(Account).first()
account_new = Account(created_by = account_old, updated_by = account_old)
session.add(account_new)
session.commit()
session.refresh(account_new)
assert account_new.created_by_id == account_old.id # pass
assert account_new.updated_by_id == account_old.id # pass
# BUT!
assert account_new.created_by == account_old # fail
assert account_new.updated_by == account_old # fail
account_new.created_by # []
account_new.updated_by # []
我看到在这种情况下,我已经将created_by_id
和updated_by_id
变成了自引用外键。 我不明白,但是,这就是为什么SQLAlchemy的未填充的相关relationship
与预期的列Account
的情况。
我究竟做错了什么?
在邻接表关系中 ,默认情况下将“方向”假定为一对多。 使用remote_side
指令remote_side
这种关系是多对一的,这是您要追求的:
def _create_relationship(cls, foreign_keys):
kwgs = {}
# Bit of a chicken or egg situation:
if cls.__name__ == "Account":
kwgs["remote_side"] = [cls.id]
return relationship("Account", foreign_keys=foreign_keys, **kwgs)
class Owned:
@declared_attr
def created_by_id(cls):
return Column(Integer, ForeignKey("accounts.id"),
nullable = True)
@declared_attr
def created_by(cls):
return _create_relationship(cls, cls.created_by_id)
@declared_attr
def updated_by_id(cls):
return Column(Integer, ForeignKey("accounts.id"),
nullable = True)
@declared_attr
def updated_by(cls):
return _create_relationship(cls, cls.updated_by_id)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.